
(function (root, name, factory) {
  'use strict';

  // Used to determine if values are of the language type `Object`
  var objectTypes = {
        'function': true
      , 'object': true
    }
    // Detect free variable `exports`
    , freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports
    // Detect free variable `module`
    , freeModule = objectTypes[typeof module] && module && !module.nodeType && module
    // Detect free variable `global`, from Node.js or Browserified code, and
    // use it as `window`
    , freeGlobal = freeExports && freeModule && typeof global === 'object' && global
    // Detect the popular CommonJS extension `module.exports`
    , moduleExports = freeModule && freeModule.exports === freeExports && freeExports;

  /* istanbul ignore else */
  if (freeGlobal && (freeGlobal.global === freeGlobal ||
                     /* istanbul ignore next */ freeGlobal.window === freeGlobal ||
                     /* istanbul ignore next */ freeGlobal.self === freeGlobal)) {
    root = freeGlobal;
  }

  // Some AMD build optimizers, like r.js, check for specific condition
  // patterns like the following:
  /* istanbul ignore if */
  if (typeof define === 'function' &&
      /* istanbul ignore next */ typeof define.amd === 'object' &&
      /* istanbul ignore next */ define.amd) {
    // defined as an anonymous module.
    define(['exports'], factory);
    // In case the source has been processed and wrapped in a define module use
    // the supplied `exports` object.
    if (freeExports && moduleExports) factory(freeModule.exports);
  }
  // check for `exports` after `define` in case a build optimizer adds an
  // `exports` object
  else /* istanbul ignore else */ if (freeExports && freeModule) {
    // in Node.js or RingoJS v0.8.0+
    /* istanbul ignore else */
    if (moduleExports) factory(freeModule.exports);
    // in Narwhal or RingoJS v0.7.0-
    else factory(freeExports);
  }
  // in a browser or Rhino
  else {
    factory((root[name] = {}));
  }
}(this, 'luaparse', function (exports) {
  'use strict';

  exports.version = '0.2.1';

  var input, options, length, features;

  // Options can be set either globally on the parser object through
  // defaultOptions, or during the parse call.
  var defaultOptions = exports.defaultOptions = {
    // Explicitly tell the parser when the input ends.
      wait: false
    // Store comments as an array in the chunk object.
    , comments: true
    // Track identifier scopes by adding an isLocal attribute to each
    // identifier-node.
    , scope: false
    // Store location information on each syntax node as
    // `loc: { start: { line, column }, end: { line, column } }`.
    , locations: false
    // Store the start and end character locations on each syntax node as
    // `range: [start, end]`.
    , ranges: false
    // A callback which will be invoked when a syntax node has been completed.
    // The node which has been created will be passed as the only parameter.
    , onCreateNode: null
    // A callback which will be invoked when a new scope is created.
    , onCreateScope: null
    // A callback which will be invoked when the current scope is destroyed.
    , onDestroyScope: null
    // A callback which will be invoked when a local variable is declared in the current scope.
    // The variable's name will be passed as the only parameter
    , onLocalDeclaration: null
    // The version of Lua targeted by the parser (string; allowed values are
    // '5.1', '5.2', '5.3').
    , luaVersion: '5.1'
    // Whether to allow code points outside the Basic Latin block in identifiers
    , extendedIdentifiers: false
  };

  // The available tokens expressed as enum flags so they can be checked with
  // bitwise operations.

  var EOF = 1, StringLiteral = 2, Keyword = 4, Identifier = 8
    , NumericLiteral = 16, Punctuator = 32, BooleanLiteral = 64
    , NilLiteral = 128, VarargLiteral = 256;

  exports.tokenTypes = { EOF: EOF, StringLiteral: StringLiteral
    , Keyword: Keyword, Identifier: Identifier, NumericLiteral: NumericLiteral
    , Punctuator: Punctuator, BooleanLiteral: BooleanLiteral
    , NilLiteral: NilLiteral, VarargLiteral: VarargLiteral
  };

  // As this parser is a bit different from luas own, the error messages
  // will be different in some situations.

  var errors = exports.errors = {
      unexpected: 'unexpected %1 \'%2\' near \'%3\''
    , expected: '\'%1\' expected near \'%2\''
    , expectedToken: '%1 expected near \'%2\''
    , unfinishedString: 'unfinished string near \'%1\''
    , malformedNumber: 'malformed number near \'%1\''
    , invalidVar: 'invalid left-hand side of assignment near \'%1\''
    , decimalEscapeTooLarge: 'decimal escape too large near \'%1\''
    , invalidEscape: 'invalid escape sequence near \'%1\''
    , hexadecimalDigitExpected: 'hexadecimal digit expected near \'%1\''
    , braceExpected: 'missing \'%1\' near \'%2\''
    , tooLargeCodepoint: 'UTF-8 value too large near \'%1\''
    , unfinishedLongString: 'unfinished long string (starting at line %1) near \'%2\''
    , unfinishedLongComment: 'unfinished long comment (starting at line %1) near \'%2\''
    , ambiguousSyntax: 'ambiguous syntax (function call x new statement) near \'%1\''
  };

  // ### Abstract Syntax Tree
  //
  // The default AST structure is inspired by the Mozilla Parser API but can
  // easily be customized by overriding these functions.

  var ast = exports.ast = {
      labelStatement: function(label) {
      return {
          type: 'LabelStatement'
        , label: label
      };
    }

    , breakStatement: function() {
      return {
          type: 'BreakStatement'
      };
    }

    , gotoStatement: function(label) {
      return {
          type: 'GotoStatement'
        , label: label
      };
    }

    , returnStatement: function(args) {
      return {
          type: 'ReturnStatement'
        , 'arguments': args
      };
    }

    , ifStatement: function(clauses) {
      return {
          type: 'IfStatement'
        , clauses: clauses
      };
    }
    , ifClause: function(condition, body) {
      return {
          type: 'IfClause'
        , condition: condition
        , body: body
      };
    }
    , elseifClause: function(condition, body) {
      return {
          type: 'ElseifClause'
        , condition: condition
        , body: body
      };
    }
    , elseClause: function(body) {
      return {
          type: 'ElseClause'
        , body: body
      };
    }

    , whileStatement: function(condition, body) {
      return {
          type: 'WhileStatement'
        , condition: condition
        , body: body
      };
    }

    , doStatement: function(body) {
      return {
          type: 'DoStatement'
        , body: body
      };
    }

    , repeatStatement: function(condition, body) {
      return {
          type: 'RepeatStatement'
        , condition: condition
        , body: body
      };
    }

    , localStatement: function(variables, init) {
      return {
          type: 'LocalStatement'
        , variables: variables
        , init: init
      };
    }

    , assignmentStatement: function(variables, init) {
      return {
          type: 'AssignmentStatement'
        , variables: variables
        , init: init
      };
    }

    , callStatement: function(expression) {
      return {
          type: 'CallStatement'
        , expression: expression
      };
    }

    , functionStatement: function(identifier, parameters, isLocal, body) {
      return {
          type: 'FunctionDeclaration'
        , identifier: identifier
        , isLocal: isLocal
        , parameters: parameters
        , body: body
      };
    }

    , forNumericStatement: function(variable, start, end, step, body) {
      return {
          type: 'ForNumericStatement'
        , variable: variable
        , start: start
        , end: end
        , step: step
        , body: body
      };
    }

    , forGenericStatement: function(variables, iterators, body) {
      return {
          type: 'ForGenericStatement'
        , variables: variables
        , iterators: iterators
        , body: body
      };
    }

    , chunk: function(body) {
      return {
          type: 'Chunk'
        , body: body
      };
    }

    , identifier: function(name) {
      return {
          type: 'Identifier'
        , name: name
      };
    }

    , literal: function(type, value, raw) {
      type = (type === StringLiteral) ? 'StringLiteral'
        : (type === NumericLiteral) ? 'NumericLiteral'
        : (type === BooleanLiteral) ? 'BooleanLiteral'
        : (type === NilLiteral) ? 'NilLiteral'
        : 'VarargLiteral';

      return {
          type: type
        , value: value
        , raw: raw
      };
    }

    , tableKey: function(key, value) {
      return {
          type: 'TableKey'
        , key: key
        , value: value
      };
    }
    , tableKeyString: function(key, value) {
      return {
          type: 'TableKeyString'
        , key: key
        , value: value
      };
    }
    , tableValue: function(value) {
      return {
          type: 'TableValue'
        , value: value
      };
    }


    , tableConstructorExpression: function(fields) {
      return {
          type: 'TableConstructorExpression'
        , fields: fields
      };
    }
    , binaryExpression: function(operator, left, right) {
      var type = ('and' === operator || 'or' === operator) ?
        'LogicalExpression' :
        'BinaryExpression';

      return {
          type: type
        , operator: operator
        , left: left
        , right: right
      };
    }
    , unaryExpression: function(operator, argument) {
      return {
          type: 'UnaryExpression'
        , operator: operator
        , argument: argument
      };
    }
    , memberExpression: function(base, indexer, identifier) {
      return {
          type: 'MemberExpression'
        , indexer: indexer
        , identifier: identifier
        , base: base
      };
    }

    , indexExpression: function(base, index) {
      return {
          type: 'IndexExpression'
        , base: base
        , index: index
      };
    }

    , callExpression: function(base, args) {
      return {
          type: 'CallExpression'
        , base: base
        , 'arguments': args
      };
    }

    , tableCallExpression: function(base, args) {
      return {
          type: 'TableCallExpression'
        , base: base
        , 'arguments': args
      };
    }

    , stringCallExpression: function(base, argument) {
      return {
          type: 'StringCallExpression'
        , base: base
        , argument: argument
      };
    }

    , comment: function(value, raw) {
      return {
          type: 'Comment'
        , value: value
        , raw: raw
      };
    }
  };

  // Wrap up the node object.

  function finishNode(node) {
    // Pop a `Marker` off the location-array and attach its location data.
    if (trackLocations) {
      var location = locations.pop();
      location.complete();
      location.bless(node);
    }
    if (options.onCreateNode) options.onCreateNode(node);
    return node;
  }


  // Helpers
  // -------

  var slice = Array.prototype.slice
    , toString = Object.prototype.toString
    , indexOf = function indexOf(array, element) {
      for (var i = 0, length = array.length; i < length; ++i) {
        if (array[i] === element) return i;
      }
      return -1;
    };

  // Iterate through an array of objects and return the index of an object
  // with a matching property.

  function indexOfObject(array, property, element) {
    for (var i = 0, length = array.length; i < length; ++i) {
      if (array[i][property] === element) return i;
    }
    return -1;
  }

  // A sprintf implementation using %index (beginning at 1) to input
  // arguments in the format string.
  //
  // Example:
  //
  //     // Unexpected function in token
  //     sprintf('Unexpected %2 in %1.', 'token', 'function');

  function sprintf(format) {
    var args = slice.call(arguments, 1);
    format = format.replace(/%(\d)/g, function (match, index) {
      return '' + args[index - 1] || /* istanbul ignore next */ '';
    });
    return format;
  }

  // Returns a new object with the properties from all objectes passed as
  // arguments. Last argument takes precedence.
  //
  // Example:
  //
  //     this.options = extend(options, { output: false });

  function extend() {
    var args = slice.call(arguments)
      , dest = {}
      , src, prop;

    for (var i = 0, length = args.length; i < length; ++i) {
      src = args[i];
      for (prop in src)
        /* istanbul ignore else */
        if (src.hasOwnProperty(prop)) {
          dest[prop] = src[prop];
        }
    }
    return dest;
  }

  // ### Error functions

  // XXX: Eliminate this function and change the error type to be different from SyntaxError.
  // This will unfortunately be a breaking change, because some downstream users depend
  // on the error thrown being an instance of SyntaxError. For example, the Ace editor:
  // <https://github.com/ajaxorg/ace/blob/4c7e5eb3f5d5ca9434847be51834a4e41661b852/lib/ace/mode/lua_worker.js#L55>

  function fixupError(e) {
    if (!Object.create)
      return e;
    return Object.create(e, {
      'line': { 'writable': true, value: e.line },
      'index': { 'writable': true, value: e.index },
      'column': { 'writable': true, value: e.column }
    });
  }

  // #### Raise an exception.
  //
  // Raise an exception by passing a token, a string format and its paramters.
  //
  // The passed tokens location will automatically be added to the error
  // message if it exists, if not it will default to the lexers current
  // position.
  //
  // Example:
  //
  //     // [1:0] expected [ near (
  //     raise(token, "expected %1 near %2", '[', token.value);

  function raise(token) {
    var message = sprintf.apply(null, slice.call(arguments, 1))
      , error, col;

    if ('undefined' !== typeof token.line) {
      col = token.range[0] - token.lineStart;
      error = fixupError(new SyntaxError(sprintf('[%1:%2] %3', token.line, col, message)));
      error.line = token.line;
      error.index = token.range[0];
      error.column = col;
    } else {
      col = index - lineStart + 1;
      error = fixupError(new SyntaxError(sprintf('[%1:%2] %3', line, col, message)));
      error.index = index;
      error.line = line;
      error.column = col;
    }
    throw error;
  }

  // #### Raise an unexpected token error.
  //
  // Example:
  //
  //     // expected <name> near '0'
  //     raiseUnexpectedToken('<name>', token);

  function raiseUnexpectedToken(type, token) {
    raise(token, errors.expectedToken, type, token.value);
  }

  // #### Raise a general unexpected error
  //
  // Usage should pass either a token object or a symbol string which was
  // expected. We can also specify a nearby token such as <eof>, this will
  // default to the currently active token.
  //
  // Example:
  //
  //     // Unexpected symbol 'end' near '<eof>'
  //     unexpected(token);
  //
  // If there's no token in the buffer it means we have reached <eof>.

  function unexpected(found) {
    var near = lookahead.value;
    if ('undefined' !== typeof found.type) {
      var type;
      switch (found.type) {
        case StringLiteral:   type = 'string';      break;
        case Keyword:         type = 'keyword';     break;
        case Identifier:      type = 'identifier';  break;
        case NumericLiteral:  type = 'number';      break;
        case Punctuator:      type = 'symbol';      break;
        case BooleanLiteral:  type = 'boolean';     break;
        case NilLiteral:
          return raise(found, errors.unexpected, 'symbol', 'nil', near);
      }
      return raise(found, errors.unexpected, type, found.value, near);
    }
    return raise(found, errors.unexpected, 'symbol', found, near);
  }

  // Lexer
  // -----
  //
  // The lexer, or the tokenizer reads the input string character by character
  // and derives a token left-right. To be as efficient as possible the lexer
  // prioritizes the common cases such as identifiers. It also works with
  // character codes instead of characters as string comparisons was the
  // biggest bottleneck of the parser.
  //
  // If `options.comments` is enabled, all comments encountered will be stored
  // in an array which later will be appended to the chunk object. If disabled,
  // they will simply be disregarded.
  //
  // When the lexer has derived a valid token, it will be returned as an object
  // containing its value and as well as its position in the input string (this
  // is always enabled to provide proper debug messages).
  //
  // `lex()` starts lexing and returns the following token in the stream.

  var index
    , token
    , previousToken
    , lookahead
    , comments
    , tokenStart
    , line
    , lineStart;

  exports.lex = lex;

  function lex() {
    skipWhiteSpace();

    // Skip comments beginning with --
    while (45 === input.charCodeAt(index) &&
           45 === input.charCodeAt(index + 1)) {
      scanComment();
      skipWhiteSpace();
    }
    if (index >= length) return {
        type : EOF
      , value: '<eof>'
      , line: line
      , lineStart: lineStart
      , range: [index, index]
    };

    var charCode = input.charCodeAt(index)
      , next = input.charCodeAt(index + 1);

    // Memorize the range index where the token begins.
    tokenStart = index;
    if (isIdentifierStart(charCode)) return scanIdentifierOrKeyword();

    switch (charCode) {
      case 39: case 34: // '"
        return scanStringLiteral();

      case 48: case 49: case 50: case 51: case 52: case 53:
      case 54: case 55: case 56: case 57: // 0-9
        return scanNumericLiteral();

      case 46: // .
        // If the dot is followed by a digit it's a float.
        if (isDecDigit(next)) return scanNumericLiteral();
        if (46 === next) {
          if (46 === input.charCodeAt(index + 2)) return scanVarargLiteral();
          return scanPunctuator('..');
        }
        return scanPunctuator('.');

      case 61: // =
        if (61 === next) return scanPunctuator('==');
        return scanPunctuator('=');

      case 62: // >
        if (features.bitwiseOperators)
          if (62 === next) return scanPunctuator('>>');
        if (61 === next) return scanPunctuator('>=');
        return scanPunctuator('>');

      case 60: // <
        if (features.bitwiseOperators)
          if (60 === next) return scanPunctuator('<<');
        if (61 === next) return scanPunctuator('<=');
        return scanPunctuator('<');

      case 126: // ~
        if (61 === next) return scanPunctuator('~=');
        if (!features.bitwiseOperators)
          break;
        return scanPunctuator('~');

      case 58: // :
        if (features.labels)
          if (58 === next) return scanPunctuator('::');
        return scanPunctuator(':');

      case 91: // [
        // Check for a multiline string, they begin with [= or [[
        if (91 === next || 61 === next) return scanLongStringLiteral();
        return scanPunctuator('[');

      case 47: // /
        // Check for integer division op (//)
        if (features.integerDivision)
          if (47 === next) return scanPunctuator('//');
        return scanPunctuator('/');

      case 38: case 124: // & |
        if (!features.bitwiseOperators)
          break;

        /* fall through */
      case 42: case 94: case 37: case 44: case 123: case 125:
      case 93: case 40: case 41: case 59: case 35: case 45:
      case 43: // * ^ % , { } ] ( ) ; # - +
        return scanPunctuator(input.charAt(index));
    }

    return unexpected(input.charAt(index));
  }

  // Whitespace has no semantic meaning in lua so simply skip ahead while
  // tracking the encounted newlines. Any kind of eol sequence is counted as a
  // single line.

  function consumeEOL() {
    var charCode = input.charCodeAt(index)
      , peekCharCode = input.charCodeAt(index + 1);

    if (isLineTerminator(charCode)) {
      // Count \n\r and \r\n as one newline.
      if (10 === charCode && 13 === peekCharCode) ++index;
      if (13 === charCode && 10 === peekCharCode) ++index;
      ++line;
      lineStart = ++index;

      return true;
    }
    return false;
  }

  function skipWhiteSpace() {
    while (index < length) {
      var charCode = input.charCodeAt(index);
      if (isWhiteSpace(charCode)) {
        ++index;
      } else if (!consumeEOL()) {
        break;
      }
    }
  }

  function encodeUTF8(codepoint) {
    if (codepoint < 0x80) {
      return String.fromCharCode(codepoint);
    } else if (codepoint < 0x800) {
      return String.fromCharCode(
        0xc0 |  (codepoint >>  6)        ,
        0x80 | ( codepoint        & 0x3f)
      );
    } else if (codepoint < 0x10000) {
      return String.fromCharCode(
        0xe0 |  (codepoint >> 12)        ,
        0x80 | ((codepoint >>  6) & 0x3f),
        0x80 | ( codepoint        & 0x3f)
      );
    } else if (codepoint < 0x110000) {
      return String.fromCharCode(
        0xf0 |  (codepoint >> 18)        ,
        0x80 | ((codepoint >> 12) & 0x3f),
        0x80 | ((codepoint >>  6) & 0x3f),
        0x80 | ( codepoint        & 0x3f)
      );
    } else {
      return null;
    }
  }

  // This function takes a JavaScript string, encodes it in WTF-8 and
  // reinterprets the resulting code units as code points; i.e. it encodes
  // the string in what was the original meaning of WTF-8.
  //
  // For a detailed rationale, see the README.md file, section
  // "Note on character encodings".

  function fixupHighCharacters(s) {
    return s.replace(/[\ud800-\udbff][\udc00-\udfff]|[^\x00-\x7f]/g, function (m) {
      if (m.length === 1)
        return encodeUTF8(m.charCodeAt(0));
      return encodeUTF8(0x10000 + (((m.charCodeAt(0) & 0x3ff) << 10) | (m.charCodeAt(1) & 0x3ff)));
    });
  }

  // Identifiers, keywords, booleans and nil all look the same syntax wise. We
  // simply go through them one by one and defaulting to an identifier if no
  // previous case matched.

  function scanIdentifierOrKeyword() {
    var value, type;

    // Slicing the input string is prefered before string concatenation in a
    // loop for performance reasons.
    while (isIdentifierPart(input.charCodeAt(++index)));
    value = fixupHighCharacters(input.slice(tokenStart, index));

    // Decide on the token type and possibly cast the value.
    if (isKeyword(value)) {
      type = Keyword;
    } else if ('true' === value || 'false' === value) {
      type = BooleanLiteral;
      value = ('true' === value);
    } else if ('nil' === value) {
      type = NilLiteral;
      value = null;
    } else {
      type = Identifier;
    }

    return {
        type: type
      , value: value
      , line: line
      , lineStart: lineStart
      , range: [tokenStart, index]
    };
  }

  // Once a punctuator reaches this function it should already have been
  // validated so we simply return it as a token.

  function scanPunctuator(value) {
    index += value.length;
    return {
        type: Punctuator
      , value: value
      , line: line
      , lineStart: lineStart
      , range: [tokenStart, index]
    };
  }

  // A vararg literal consists of three dots.

  function scanVarargLiteral() {
    index += 3;
    return {
        type: VarargLiteral
      , value: '...'
      , line: line
      , lineStart: lineStart
      , range: [tokenStart, index]
    };
  }

  // Find the string literal by matching the delimiter marks used.

  function scanStringLiteral() {
    var delimiter = input.charCodeAt(index++)
      , beginLine = line
      , beginLineStart = lineStart
      , stringStart = index
      , string = ''
      , charCode;

    while (index < length) {
      charCode = input.charCodeAt(index++);
      if (delimiter === charCode) break;
      if (92 === charCode) { // backslash
        string += fixupHighCharacters(input.slice(stringStart, index - 1)) + readEscapeSequence();
        stringStart = index;
      }
      // EOF or `\n` terminates a string literal. If we haven't found the
      // ending delimiter by now, raise an exception.
      else if (index >= length || isLineTerminator(charCode)) {
        string += input.slice(stringStart, index - 1);
        raise({}, errors.unfinishedString, string + String.fromCharCode(charCode));
      }
    }
    string += fixupHighCharacters(input.slice(stringStart, index - 1));

    return {
        type: StringLiteral
      , value: string
      , line: beginLine
      , lineStart: beginLineStart
      , lastLine: line
      , lastLineStart: lineStart
      , range: [tokenStart, index]
    };
  }

  // Expect a multiline string literal and return it as a regular string
  // literal, if it doesn't validate into a valid multiline string, throw an
  // exception.

  function scanLongStringLiteral() {
    var beginLine = line
      , beginLineStart = lineStart
      , string = readLongString(false);
    // Fail if it's not a multiline literal.
    if (false === string) raise(token, errors.expected, '[', token.value);

    return {
        type: StringLiteral
      , value: fixupHighCharacters(string)
      , line: beginLine
      , lineStart: beginLineStart
      , lastLine: line
      , lastLineStart: lineStart
      , range: [tokenStart, index]
    };
  }

  // Numeric literals will be returned as floating-point numbers instead of
  // strings. The raw value should be retrieved from slicing the input string
  // later on in the process.
  //
  // If a hexadecimal number is encountered, it will be converted.

  function scanNumericLiteral() {
    var character = input.charAt(index)
      , next = input.charAt(index + 1);

    var value = ('0' === character && 'xX'.indexOf(next || null) >= 0) ?
      readHexLiteral() : readDecLiteral();

    return {
        type: NumericLiteral
      , value: value
      , line: line
      , lineStart: lineStart
      , range: [tokenStart, index]
    };
  }

  // Lua hexadecimals have an optional fraction part and an optional binary
  // exoponent part. These are not included in JavaScript so we will compute
  // all three parts separately and then sum them up at the end of the function
  // with the following algorithm.
  //
  //     Digit := toDec(digit)
  //     Fraction := toDec(fraction) / 16 ^ fractionCount
  //     BinaryExp := 2 ^ binaryExp
  //     Number := ( Digit + Fraction ) * BinaryExp

  function readHexLiteral() {
    var fraction = 0 // defaults to 0 as it gets summed
      , binaryExponent = 1 // defaults to 1 as it gets multiplied
      , binarySign = 1 // positive
      , digit, fractionStart, exponentStart, digitStart;

    digitStart = index += 2; // Skip 0x part

    // A minimum of one hex digit is required.
    if (!isHexDigit(input.charCodeAt(index)))
      raise({}, errors.malformedNumber, input.slice(tokenStart, index));

    while (isHexDigit(input.charCodeAt(index))) ++index;
    // Convert the hexadecimal digit to base 10.
    digit = parseInt(input.slice(digitStart, index), 16);

    // Fraction part i optional.
    if ('.' === input.charAt(index)) {
      fractionStart = ++index;

      while (isHexDigit(input.charCodeAt(index))) ++index;
      fraction = input.slice(fractionStart, index);

      // Empty fraction parts should default to 0, others should be converted
      // 0.x form so we can use summation at the end.
      fraction = (fractionStart === index) ? 0
        : parseInt(fraction, 16) / Math.pow(16, index - fractionStart);
    }

    // Binary exponents are optional
    if ('pP'.indexOf(input.charAt(index) || null) >= 0) {
      ++index;

      // Sign part is optional and defaults to 1 (positive).
      if ('+-'.indexOf(input.charAt(index) || null) >= 0)
        binarySign = ('+' === input.charAt(index++)) ? 1 : -1;

      exponentStart = index;

      // The binary exponent sign requires a decimal digit.
      if (!isDecDigit(input.charCodeAt(index)))
        raise({}, errors.malformedNumber, input.slice(tokenStart, index));

      while (isDecDigit(input.charCodeAt(index))) ++index;
      binaryExponent = input.slice(exponentStart, index);

      // Calculate the binary exponent of the number.
      binaryExponent = Math.pow(2, binaryExponent * binarySign);
    }

    return (digit + fraction) * binaryExponent;
  }

  // Decimal numbers are exactly the same in Lua and in JavaScript, because of
  // this we check where the token ends and then parse it with native
  // functions.

  function readDecLiteral() {
    while (isDecDigit(input.charCodeAt(index))) ++index;
    // Fraction part is optional
    if ('.' === input.charAt(index)) {
      ++index;
      // Fraction part defaults to 0
      while (isDecDigit(input.charCodeAt(index))) ++index;
    }
    // Exponent part is optional.
    if ('eE'.indexOf(input.charAt(index) || null) >= 0) {
      ++index;
      // Sign part is optional.
      if ('+-'.indexOf(input.charAt(index) || null) >= 0) ++index;
      // An exponent is required to contain at least one decimal digit.
      if (!isDecDigit(input.charCodeAt(index)))
        raise({}, errors.malformedNumber, input.slice(tokenStart, index));

      while (isDecDigit(input.charCodeAt(index))) ++index;
    }

    return parseFloat(input.slice(tokenStart, index));
  }

  function readUnicodeEscapeSequence() {
    var sequenceStart = index++;

    if (input.charAt(index++) !== '{')
      raise({}, errors.braceExpected, '{', '\\' + input.slice(sequenceStart, index));
    if (!isHexDigit(input.charCodeAt(index)))
      raise({}, errors.hexadecimalDigitExpected, '\\' + input.slice(sequenceStart, index));

    while (input.charCodeAt(index) === 0x30) ++index;
    var escStart = index;

    while (isHexDigit(input.charCodeAt(index))) {
      ++index;
      if (index - escStart > 6)
        raise({}, errors.tooLargeCodepoint, '\\' + input.slice(sequenceStart, index));
    }

    var b = input.charAt(index++);
    if (b !== '}') {
      if ((b === '"') || (b === "'"))
        raise({}, errors.braceExpected, '}', '\\' + input.slice(sequenceStart, index--));
      else
        raise({}, errors.hexadecimalDigitExpected, '\\' + input.slice(sequenceStart, index));
    }

    var codepoint = parseInt(input.slice(escStart, index - 1), 16);

    codepoint = encodeUTF8(codepoint);
    if (codepoint === null) {
      raise({}, errors.tooLargeCodepoint, '\\' + input.slice(sequenceStart, index));
    }
    return codepoint;
  }

  // Translate escape sequences to the actual characters.
  function readEscapeSequence() {
    var sequenceStart = index;
    switch (input.charAt(index)) {
      // Lua allow the following escape sequences.
      case 'a': ++index; return '\x07';
      case 'n': ++index; return '\n';
      case 'r': ++index; return '\r';
      case 't': ++index; return '\t';
      case 'v': ++index; return '\x0b';
      case 'b': ++index; return '\b';
      case 'f': ++index; return '\f';

      // Backslash at the end of the line. We treat all line endings as equivalent,
      // and as representing the [LF] character (code 10). Lua 5.1 through 5.3
      // have been verified to behave the same way.
      case '\r':
      case '\n':
        consumeEOL();
        return '\n';

      case '0': case '1': case '2': case '3': case '4':
      case '5': case '6': case '7': case '8': case '9':
        // \ddd, where ddd is a sequence of up to three decimal digits.
        while (isDecDigit(input.charCodeAt(index)) && index - sequenceStart < 3) ++index;

        var ddd = parseInt(input.slice(sequenceStart, index), 10);
        if (ddd > 255) {
          raise({}, errors.decimalEscapeTooLarge, '\\' + ddd);
        }
        return String.fromCharCode(ddd);

      case 'z':
        if (features.skipWhitespaceEscape) {
          ++index;
          skipWhiteSpace();
          return '';
        }

        /* fall through */
      case 'x':
        if (features.hexEscapes) {
          // \xXX, where XX is a sequence of exactly two hexadecimal digits
          if (isHexDigit(input.charCodeAt(index + 1)) &&
              isHexDigit(input.charCodeAt(index + 2))) {
            index += 3;
            return String.fromCharCode(parseInt(input.slice(sequenceStart + 1, index), 16));
          }
          raise({}, errors.hexadecimalDigitExpected, '\\' + input.slice(sequenceStart, index + 2));
        }

        /* fall through */
      case 'u':
        if (features.unicodeEscapes) {
          return readUnicodeEscapeSequence();
        }

        /* fall through */
      default:
        if (features.strictEscapes)
          raise({}, errors.invalidEscape, '\\' + input.slice(sequenceStart, index + 1));

        /* fall through */
      case '\\': case '"': case "'":
        return input.charAt(index++);
    }
  }

  // Comments begin with -- after which it will be decided if they are
  // multiline comments or not.
  //
  // The multiline functionality works the exact same way as with string
  // literals so we reuse the functionality.

  function scanComment() {
    tokenStart = index;
    index += 2; // --

    var character = input.charAt(index)
      , content = ''
      , isLong = false
      , commentStart = index
      , lineStartComment = lineStart
      , lineComment = line;

    if ('[' === character) {
      content = readLongString(true);
      // This wasn't a multiline comment after all.
      if (false === content) content = character;
      else isLong = true;
    }
    // Scan until next line as long as it's not a multiline comment.
    if (!isLong) {
      while (index < length) {
        if (isLineTerminator(input.charCodeAt(index))) break;
        ++index;
      }
      if (options.comments) content = input.slice(commentStart, index);
    }

    if (options.comments) {
      var node = ast.comment(content, input.slice(tokenStart, index));

      // `Marker`s depend on tokens available in the parser and as comments are
      // intercepted in the lexer all location data is set manually.
      if (options.locations) {
        node.loc = {
            start: { line: lineComment, column: tokenStart - lineStartComment }
          , end: { line: line, column: index - lineStart }
        };
      }
      if (options.ranges) {
        node.range = [tokenStart, index];
      }
      if (options.onCreateNode) options.onCreateNode(node);
      comments.push(node);
    }
  }

  // Read a multiline string by calculating the depth of `=` characters and
  // then appending until an equal depth is found.

  function readLongString(isComment) {
    var level = 0
      , content = ''
      , terminator = false
      , character, stringStart, firstLine = line;

    ++index; // [

    // Calculate the depth of the comment.
    while ('=' === input.charAt(index + level)) ++level;
    // Exit, this is not a long string afterall.
    if ('[' !== input.charAt(index + level)) return false;

    index += level + 1;

    // If the first character is a newline, ignore it and begin on next line.
    if (isLineTerminator(input.charCodeAt(index))) consumeEOL();

    stringStart = index;
    while (index < length) {
      // To keep track of line numbers run the `consumeEOL()` which increments
      // its counter.
      while (isLineTerminator(input.charCodeAt(index))) consumeEOL();

      character = input.charAt(index++);

      // Once the delimiter is found, iterate through the depth count and see
      // if it matches.
      if (']' === character) {
        terminator = true;
        for (var i = 0; i < level; ++i) {
          if ('=' !== input.charAt(index + i)) terminator = false;
        }
        if (']' !== input.charAt(index + level)) terminator = false;
      }

      // We reached the end of the multiline string. Get out now.
      if (terminator) {
        content += input.slice(stringStart, index - 1);
        index += level + 1;
        return content;
      }
    }

    raise({}, isComment ?
              errors.unfinishedLongComment :
              errors.unfinishedLongString,
          firstLine, '<eof>');
  }

  // ## Lex functions and helpers.

  // Read the next token.
  //
  // This is actually done by setting the current token to the lookahead and
  // reading in the new lookahead token.

  function next() {
    previousToken = token;
    token = lookahead;
    lookahead = lex();
  }

  // Consume a token if its value matches. Once consumed or not, return the
  // success of the operation.

  function consume(value) {
    if (value === token.value) {
      next();
      return true;
    }
    return false;
  }

  // Expect the next token value to match. If not, throw an exception.

  function expect(value) {
    if (value === token.value) next();
    else raise(token, errors.expected, value, token.value);
  }

  // ### Validation functions

  function isWhiteSpace(charCode) {
    return 9 === charCode || 32 === charCode || 0xB === charCode || 0xC === charCode;
  }

  function isLineTerminator(charCode) {
    return 10 === charCode || 13 === charCode;
  }

  function isDecDigit(charCode) {
    return charCode >= 48 && charCode <= 57;
  }

  function isHexDigit(charCode) {
    return (charCode >= 48 && charCode <= 57) || (charCode >= 97 && charCode <= 102) || (charCode >= 65 && charCode <= 70);
  }

  // From [Lua 5.2](http://www.lua.org/manual/5.2/manual.html#8.1) onwards
  // identifiers cannot use 'locale-dependent' letters (i.e. dependent on the C locale).
  // On the other hand, LuaJIT allows arbitrary octets ≥ 128 in identifiers.

  function isIdentifierStart(charCode) {
    if ((charCode >= 65 && charCode <= 90) || (charCode >= 97 && charCode <= 122) || 95 === charCode)
      return true;
    if (options.extendedIdentifiers && charCode >= 128)
      return true;
    return false;
  }

  function isIdentifierPart(charCode) {
    if ((charCode >= 65 && charCode <= 90) || (charCode >= 97 && charCode <= 122) || 95 === charCode || (charCode >= 48 && charCode <= 57))
      return true;
    if (options.extendedIdentifiers && charCode >= 128)
      return true;
    return false;
  }

  // [3.1 Lexical Conventions](http://www.lua.org/manual/5.2/manual.html#3.1)
  //
  // `true`, `false` and `nil` will not be considered keywords, but literals.

  function isKeyword(id) {
    switch (id.length) {
      case 2:
        return 'do' === id || 'if' === id || 'in' === id || 'or' === id;
      case 3:
        return 'and' === id || 'end' === id || 'for' === id || 'not' === id;
      case 4:
        if ('else' === id || 'then' === id)
          return true;
        if (features.labels && !features.contextualGoto)
          return ('goto' === id);
        return false;
      case 5:
        return 'break' === id || 'local' === id || 'until' === id || 'while' === id;
      case 6:
        return 'elseif' === id || 'repeat' === id || 'return' === id;
      case 8:
        return 'function' === id;
    }
    return false;
  }

  function isUnary(token) {
    if (Punctuator === token.type) return '#-~'.indexOf(token.value) >= 0;
    if (Keyword === token.type) return 'not' === token.value;
    return false;
  }

  // @TODO this needs to be rethought.
  function isCallExpression(expression) {
    switch (expression.type) {
      case 'CallExpression':
      case 'TableCallExpression':
      case 'StringCallExpression':
        return true;
    }
    return false;
  }

  // Check if the token syntactically closes a block.

  function isBlockFollow(token) {
    if (EOF === token.type) return true;
    if (Keyword !== token.type) return false;
    switch (token.value) {
      case 'else': case 'elseif':
      case 'end': case 'until':
        return true;
      default:
        return false;
    }
  }

  // Scope
  // -----

  // Store each block scope as a an array of identifier names. Each scope is
  // stored in an FILO-array.
  var scopes
    // The current scope index
    , scopeDepth
    // A list of all global identifier nodes.
    , globals;

  // Create a new scope inheriting all declarations from the previous scope.
  function createScope() {
    var scope = Array.apply(null, scopes[scopeDepth++]);
    scopes.push(scope);
    if (options.onCreateScope) options.onCreateScope();
  }

  // Exit and remove the current scope.
  function destroyScope() {
    var scope = scopes.pop();
    scopeDepth--;
    if (options.onDestroyScope) options.onDestroyScope();
  }

  // Add identifier name to the current scope if it doesnt already exist.
  function scopeIdentifierName(name) {
    if (options.onLocalDeclaration) options.onLocalDeclaration(name);
    if (-1 !== indexOf(scopes[scopeDepth], name)) return;
    scopes[scopeDepth].push(name);
  }

  // Add identifier to the current scope
  function scopeIdentifier(node) {
    scopeIdentifierName(node.name);
    attachScope(node, true);
  }

  // Attach scope information to node. If the node is global, store it in the
  // globals array so we can return the information to the user.
  function attachScope(node, isLocal) {
    if (!isLocal && -1 === indexOfObject(globals, 'name', node.name))
      globals.push(node);

    node.isLocal = isLocal;
  }

  // Is the identifier name available in this scope.
  function scopeHasName(name) {
    return (-1 !== indexOf(scopes[scopeDepth], name));
  }

  // Location tracking
  // -----------------
  //
  // Locations are stored in FILO-array as a `Marker` object consisting of both
  // `loc` and `range` data. Once a `Marker` is popped off the list an end
  // location is added and the data is attached to a syntax node.

  var locations = []
    , trackLocations;

  function createLocationMarker() {
    return new Marker(token);
  }

  function Marker(token) {
    if (options.locations) {
      this.loc = {
          start: {
            line: token.line
          , column: token.range[0] - token.lineStart
        }
        , end: {
            line: 0
          , column: 0
        }
      };
    }
    if (options.ranges) this.range = [token.range[0], 0];
  }

  // Complete the location data stored in the `Marker` by adding the location
  // of the *previous token* as an end location.
  Marker.prototype.complete = function() {
    if (options.locations) {
      this.loc.end.line = previousToken.lastLine || previousToken.line;
      this.loc.end.column = previousToken.range[1] - (previousToken.lastLineStart || previousToken.lineStart);
    }
    if (options.ranges) {
      this.range[1] = previousToken.range[1];
    }
  };

  Marker.prototype.bless = function (node) {
    if (this.loc) {
      var loc = this.loc;
      node.loc = {
        start: {
          line: loc.start.line,
          column: loc.start.column
        },
        end: {
          line: loc.end.line,
          column: loc.end.column
        }
      };
    }
    if (this.range) {
      node.range = [
        this.range[0],
        this.range[1]
      ];
    }
  };

  // Create a new `Marker` and add it to the FILO-array.
  function markLocation() {
    if (trackLocations) locations.push(createLocationMarker());
  }

  // Push an arbitrary `Marker` object onto the FILO-array.
  function pushLocation(marker) {
    if (trackLocations) locations.push(marker);
  }

  // Parse functions
  // ---------------

  // Chunk is the main program object. Syntactically it's the same as a block.
  //
  //     chunk ::= block

  function parseChunk() {
    next();
    markLocation();
    if (options.scope) createScope();
    var body = parseBlock();
    if (options.scope) destroyScope();
    if (EOF !== token.type) unexpected(token);
    // If the body is empty no previousToken exists when finishNode runs.
    if (trackLocations && !body.length) previousToken = token;
    return finishNode(ast.chunk(body));
  }

  // A block contains a list of statements with an optional return statement
  // as its last statement.
  //
  //     block ::= {stat} [retstat]

  function parseBlock(terminator) {
    var block = []
      , statement;

    while (!isBlockFollow(token)) {
      // Return has to be the last statement in a block.
      if ('return' === token.value) {
        block.push(parseStatement());
        break;
      }
      statement = parseStatement();
      consume(';');
      // Statements are only added if they are returned, this allows us to
      // ignore some statements, such as EmptyStatement.
      if (statement) block.push(statement);
    }

    // Doesn't really need an ast node
    return block;
  }

  // There are two types of statements, simple and compound.
  //
  //     statement ::= break | goto | do | while | repeat | return
  //          | if | for | function | local | label | assignment
  //          | functioncall | ';'

  function parseStatement() {
    markLocation();
    if (Keyword === token.type) {
      switch (token.value) {
        case 'local':    next(); return parseLocalStatement();
        case 'if':       next(); return parseIfStatement();
        case 'return':   next(); return parseReturnStatement();
        case 'function': next();
          var name = parseFunctionName();
          return parseFunctionDeclaration(name);
        case 'while':    next(); return parseWhileStatement();
        case 'for':      next(); return parseForStatement();
        case 'repeat':   next(); return parseRepeatStatement();
        case 'break':    next(); return parseBreakStatement();
        case 'do':       next(); return parseDoStatement();
        case 'goto':     next(); return parseGotoStatement();
      }
    }

    if (features.contextualGoto &&
        token.type === Identifier && token.value === 'goto' &&
        lookahead.type === Identifier && lookahead.value !== 'goto') {
      next(); return parseGotoStatement();
    }

    if (Punctuator === token.type) {
      if (consume('::')) return parseLabelStatement();
    }
    // Assignments memorizes the location and pushes it manually for wrapper
    // nodes. Additionally empty `;` statements should not mark a location.
    if (trackLocations) locations.pop();

    // When a `;` is encounted, simply eat it without storing it.
    if (features.emptyStatement) {
      if (consume(';')) return;
    }

    return parseAssignmentOrCallStatement();
  }

  // ## Statements

  //     label ::= '::' Name '::'

  function parseLabelStatement() {
    var name = token.value
      , label = parseIdentifier();

    if (options.scope) {
      scopeIdentifierName('::' + name + '::');
      attachScope(label, true);
    }

    expect('::');
    return finishNode(ast.labelStatement(label));
  }

  //     break ::= 'break'

  function parseBreakStatement() {
    return finishNode(ast.breakStatement());
  }

  //     goto ::= 'goto' Name

  function parseGotoStatement() {
    var name = token.value
      , label = parseIdentifier();

    return finishNode(ast.gotoStatement(label));
  }

  //     do ::= 'do' block 'end'

  function parseDoStatement() {
    if (options.scope) createScope();
    var body = parseBlock();
    if (options.scope) destroyScope();
    expect('end');
    return finishNode(ast.doStatement(body));
  }

  //     while ::= 'while' exp 'do' block 'end'

  function parseWhileStatement() {
    var condition = parseExpectedExpression();
    expect('do');
    if (options.scope) createScope();
    var body = parseBlock();
    if (options.scope) destroyScope();
    expect('end');
    return finishNode(ast.whileStatement(condition, body));
  }

  //     repeat ::= 'repeat' block 'until' exp

  function parseRepeatStatement() {
    if (options.scope) createScope();
    var body = parseBlock();
    expect('until');
    var condition = parseExpectedExpression();
    if (options.scope) destroyScope();
    return finishNode(ast.repeatStatement(condition, body));
  }

  //     retstat ::= 'return' [exp {',' exp}] [';']

  function parseReturnStatement() {
    var expressions = [];

    if ('end' !== token.value) {
      var expression = parseExpression();
      if (null != expression) expressions.push(expression);
      while (consume(',')) {
        expression = parseExpectedExpression();
        expressions.push(expression);
      }
      consume(';'); // grammar tells us ; is optional here.
    }
    return finishNode(ast.returnStatement(expressions));
  }

  //     if ::= 'if' exp 'then' block {elif} ['else' block] 'end'
  //     elif ::= 'elseif' exp 'then' block

  function parseIfStatement() {
    var clauses = []
      , condition
      , body
      , marker;

    // IfClauses begin at the same location as the parent IfStatement.
    // It ends at the start of `end`, `else`, or `elseif`.
    if (trackLocations) {
      marker = locations[locations.length - 1];
      locations.push(marker);
    }
    condition = parseExpectedExpression();
    expect('then');
    if (options.scope) createScope();
    body = parseBlock();
    if (options.scope) destroyScope();
    clauses.push(finishNode(ast.ifClause(condition, body)));

    if (trackLocations) marker = createLocationMarker();
    while (consume('elseif')) {
      pushLocation(marker);
      condition = parseExpectedExpression();
      expect('then');
      if (options.scope) createScope();
      body = parseBlock();
      if (options.scope) destroyScope();
      clauses.push(finishNode(ast.elseifClause(condition, body)));
      if (trackLocations) marker = createLocationMarker();
    }

    if (consume('else')) {
      // Include the `else` in the location of ElseClause.
      if (trackLocations) {
        marker = new Marker(previousToken);
        locations.push(marker);
      }
      if (options.scope) createScope();
      body = parseBlock();
      if (options.scope) destroyScope();
      clauses.push(finishNode(ast.elseClause(body)));
    }

    expect('end');
    return finishNode(ast.ifStatement(clauses));
  }

  // There are two types of for statements, generic and numeric.
  //
  //     for ::= Name '=' exp ',' exp [',' exp] 'do' block 'end'
  //     for ::= namelist 'in' explist 'do' block 'end'
  //     namelist ::= Name {',' Name}
  //     explist ::= exp {',' exp}

  function parseForStatement() {
    var variable = parseIdentifier()
      , body;

    // The start-identifier is local.

    if (options.scope) {
      createScope();
      scopeIdentifier(variable);
    }

    // If the first expression is followed by a `=` punctuator, this is a
    // Numeric For Statement.
    if (consume('=')) {
      // Start expression
      var start = parseExpectedExpression();
      expect(',');
      // End expression
      var end = parseExpectedExpression();
      // Optional step expression
      var step = consume(',') ? parseExpectedExpression() : null;

      expect('do');
      body = parseBlock();
      expect('end');
      if (options.scope) destroyScope();

      return finishNode(ast.forNumericStatement(variable, start, end, step, body));
    }
    // If not, it's a Generic For Statement
    else {
      // The namelist can contain one or more identifiers.
      var variables = [variable];
      while (consume(',')) {
        variable = parseIdentifier();
        // Each variable in the namelist is locally scoped.
        if (options.scope) scopeIdentifier(variable);
        variables.push(variable);
      }
      expect('in');
      var iterators = [];

      // One or more expressions in the explist.
      do {
        var expression = parseExpectedExpression();
        iterators.push(expression);
      } while (consume(','));

      expect('do');
      body = parseBlock();
      expect('end');
      if (options.scope) destroyScope();

      return finishNode(ast.forGenericStatement(variables, iterators, body));
    }
  }

  // Local statements can either be variable assignments or function
  // definitions. If a function definition is found, it will be delegated to
  // `parseFunctionDeclaration()` with the isLocal flag.
  //
  // This AST structure might change into a local assignment with a function
  // child.
  //
  //     local ::= 'local' 'function' Name funcdecl
  //        | 'local' Name {',' Name} ['=' exp {',' exp}]

  function parseLocalStatement() {
    var name;

    if (Identifier === token.type) {
      var variables = []
        , init = [];

      do {
        name = parseIdentifier();

        variables.push(name);
      } while (consume(','));

      if (consume('=')) {
        do {
          var expression = parseExpectedExpression();
          init.push(expression);
        } while (consume(','));
      }

      // Declarations doesn't exist before the statement has been evaluated.
      // Therefore assignments can't use their declarator. And the identifiers
      // shouldn't be added to the scope until the statement is complete.
      if (options.scope) {
        for (var i = 0, l = variables.length; i < l; ++i) {
          scopeIdentifier(variables[i]);
        }
      }

      return finishNode(ast.localStatement(variables, init));
    }
    if (consume('function')) {
      name = parseIdentifier();

      if (options.scope) {
        scopeIdentifier(name);
        createScope();
      }

      // MemberExpressions are not allowed in local function statements.
      return parseFunctionDeclaration(name, true);
    } else {
      raiseUnexpectedToken('<name>', token);
    }
  }

  function validateVar(node) {
    // @TODO we need something not dependent on the exact AST used. see also isCallExpression()
    if (node.inParens || (['Identifier', 'MemberExpression', 'IndexExpression'].indexOf(node.type) === -1)) {
      raise(token, errors.invalidVar, token.value);
    }
  }

  //     assignment ::= varlist '=' explist
  //     var ::= Name | prefixexp '[' exp ']' | prefixexp '.' Name
  //     varlist ::= var {',' var}
  //     explist ::= exp {',' exp}
  //
  //     call ::= callexp
  //     callexp ::= prefixexp args | prefixexp ':' Name args

  function parseAssignmentOrCallStatement() {
    // Keep a reference to the previous token for better error messages in case
    // of invalid statement
    var previous = token
      , expression, marker;

    if (trackLocations) marker = createLocationMarker();
    expression = parsePrefixExpression();

    if (null == expression) return unexpected(token);
    if (',='.indexOf(token.value) >= 0) {
      var variables = [expression]
        , init = []
        , exp;

      validateVar(expression);
      while (consume(',')) {
        exp = parsePrefixExpression();
        if (null == exp) raiseUnexpectedToken('<expression>', token);
        validateVar(exp);
        variables.push(exp);
      }
      expect('=');
      do {
        exp = parseExpectedExpression();
        init.push(exp);
      } while (consume(','));

      pushLocation(marker);
      return finishNode(ast.assignmentStatement(variables, init));
    }
    if (isCallExpression(expression)) {
      pushLocation(marker);
      return finishNode(ast.callStatement(expression));
    }
    // The prefix expression was neither part of an assignment or a
    // callstatement, however as it was valid it's been consumed, so raise
    // the exception on the previous token to provide a helpful message.
    return unexpected(previous);
  }



  // ### Non-statements

  //     Identifier ::= Name

  function parseIdentifier() {
    markLocation();
    var identifier = token.value;
    if (Identifier !== token.type) raiseUnexpectedToken('<name>', token);
    next();
    return finishNode(ast.identifier(identifier));
  }

  // Parse the functions parameters and body block. The name should already
  // have been parsed and passed to this declaration function. By separating
  // this we allow for anonymous functions in expressions.
  //
  // For local functions there's a boolean parameter which needs to be set
  // when parsing the declaration.
  //
  //     funcdecl ::= '(' [parlist] ')' block 'end'
  //     parlist ::= Name {',' Name} | [',' '...'] | '...'

  function parseFunctionDeclaration(name, isLocal) {
    var parameters = [];
    expect('(');

    // The declaration has arguments
    if (!consume(')')) {
      // Arguments are a comma separated list of identifiers, optionally ending
      // with a vararg.
      while (true) {
        if (Identifier === token.type) {
          var parameter = parseIdentifier();
          // Function parameters are local.
          if (options.scope) scopeIdentifier(parameter);

          parameters.push(parameter);

          if (consume(',')) continue;
          else if (consume(')')) break;
        }
        // No arguments are allowed after a vararg.
        else if (VarargLiteral === token.type) {
          parameters.push(parsePrimaryExpression());
          expect(')');
          break;
        } else {
          raiseUnexpectedToken('<name> or \'...\'', token);
        }
      }
    }

    var body = parseBlock();
    expect('end');
    if (options.scope) destroyScope();

    isLocal = isLocal || false;
    return finishNode(ast.functionStatement(name, parameters, isLocal, body));
  }

  // Parse the function name as identifiers and member expressions.
  //
  //     Name {'.' Name} [':' Name]

  function parseFunctionName() {
    var base, name, marker;

    if (trackLocations) marker = createLocationMarker();
    base = parseIdentifier();

    if (options.scope) {
      attachScope(base, scopeHasName(base.name));
      createScope();
    }

    while (consume('.')) {
      pushLocation(marker);
      name = parseIdentifier();
      base = finishNode(ast.memberExpression(base, '.', name));
    }

    if (consume(':')) {
      pushLocation(marker);
      name = parseIdentifier();
      base = finishNode(ast.memberExpression(base, ':', name));
      if (options.scope) scopeIdentifierName('self');
    }

    return base;
  }

  //     tableconstructor ::= '{' [fieldlist] '}'
  //     fieldlist ::= field {fieldsep field} fieldsep
  //     field ::= '[' exp ']' '=' exp | Name = 'exp' | exp
  //
  //     fieldsep ::= ',' | ';'

  function parseTableConstructor() {
    var fields = []
      , key, value;

    while (true) {
      markLocation();
      if (Punctuator === token.type && consume('[')) {
        key = parseExpectedExpression();
        expect(']');
        expect('=');
        value = parseExpectedExpression();
        fields.push(finishNode(ast.tableKey(key, value)));
      } else if (Identifier === token.type) {
        if ('=' === lookahead.value) {
          key = parseIdentifier();
          next();
          value = parseExpectedExpression();
          fields.push(finishNode(ast.tableKeyString(key, value)));
        } else {
          value = parseExpectedExpression();
          fields.push(finishNode(ast.tableValue(value)));
        }
      } else {
        if (null == (value = parseExpression())) {
          locations.pop();
          break;
        }
        fields.push(finishNode(ast.tableValue(value)));
      }
      if (',;'.indexOf(token.value) >= 0) {
        next();
        continue;
      }
      break;
    }
    expect('}');
    return finishNode(ast.tableConstructorExpression(fields));
  }

  // Expression parser
  // -----------------
  //
  // Expressions are evaluated and always return a value. If nothing is
  // matched null will be returned.
  //
  //     exp ::= (unop exp | primary | prefixexp ) { binop exp }
  //
  //     primary ::= nil | false | true | Number | String | '...'
  //          | functiondef | tableconstructor
  //
  //     prefixexp ::= (Name | '(' exp ')' ) { '[' exp ']'
  //          | '.' Name | ':' Name args | args }
  //

  function parseExpression() {
    var expression = parseSubExpression(0);
    return expression;
  }

  // Parse an expression expecting it to be valid.

  function parseExpectedExpression() {
    var expression = parseExpression();
    if (null == expression) raiseUnexpectedToken('<expression>', token);
    else return expression;
  }


  // Return the precedence priority of the operator.
  //
  // As unary `-` can't be distinguished from binary `-`, unary precedence
  // isn't described in this table but in `parseSubExpression()` itself.
  //
  // As this function gets hit on every expression it's been optimized due to
  // the expensive CompareICStub which took ~8% of the parse time.

  function binaryPrecedence(operator) {
    var charCode = operator.charCodeAt(0)
      , length = operator.length;

    if (1 === length) {
      switch (charCode) {
        case 94: return 12; // ^
        case 42: case 47: case 37: return 10; // * / %
        case 43: case 45: return 9; // + -
        case 38: return 6; // &
        case 126: return 5; // ~
        case 124: return 4; // |
        case 60: case 62: return 3; // < >
      }
    } else if (2 === length) {
      switch (charCode) {
        case 47: return 10; // //
        case 46: return 8; // ..
        case 60: case 62:
            if('<<' === operator || '>>' === operator) return 7; // << >>
            return 3; // <= >=
        case 61: case 126: return 3; // == ~=
        case 111: return 1; // or
      }
    } else if (97 === charCode && 'and' === operator) return 2;
    return 0;
  }

  // Implement an operator-precedence parser to handle binary operator
  // precedence.
  //
  // We use this algorithm because it's compact, it's fast and Lua core uses
  // the same so we can be sure our expressions are parsed in the same manner
  // without excessive amounts of tests.
  //
  //     exp ::= (unop exp | primary | prefixexp ) { binop exp }

  function parseSubExpression(minPrecedence) {
    var operator = token.value
    // The left-hand side in binary operations.
      , expression, marker;

    if (trackLocations) marker = createLocationMarker();

    // UnaryExpression
    if (isUnary(token)) {
      markLocation();
      next();
      var argument = parseSubExpression(10);
      if (argument == null) raiseUnexpectedToken('<expression>', token);
      expression = finishNode(ast.unaryExpression(operator, argument));
    }
    if (null == expression) {
      // PrimaryExpression
      expression = parsePrimaryExpression();

      // PrefixExpression
      if (null == expression) {
        expression = parsePrefixExpression();
      }
    }
    // This is not a valid left hand expression.
    if (null == expression) return null;

    var precedence;
    while (true) {
      operator = token.value;

      precedence = (Punctuator === token.type || Keyword === token.type) ?
        binaryPrecedence(operator) : 0;

      if (precedence === 0 || precedence <= minPrecedence) break;
      // Right-hand precedence operators
      if ('^' === operator || '..' === operator) precedence--;
      next();
      var right = parseSubExpression(precedence);
      if (null == right) raiseUnexpectedToken('<expression>', token);
      // Push in the marker created before the loop to wrap its entirety.
      if (trackLocations) locations.push(marker);
      expression = finishNode(ast.binaryExpression(operator, expression, right));

    }
    return expression;
  }

  //     prefixexp ::= prefix {suffix}
  //     prefix ::= Name | '(' exp ')'
  //     suffix ::= '[' exp ']' | '.' Name | ':' Name args | args
  //
  //     args ::= '(' [explist] ')' | tableconstructor | String

  function parsePrefixExpression() {
    var base, name, marker;

    if (trackLocations) marker = createLocationMarker();

    // The prefix
    if (Identifier === token.type) {
      name = token.value;
      base = parseIdentifier();
      // Set the parent scope.
      if (options.scope) attachScope(base, scopeHasName(name));
    } else if (consume('(')) {
      base = parseExpectedExpression();
      expect(')');
      base.inParens = true; // XXX: quick and dirty. needed for validateVar
    } else {
      return null;
    }

    // The suffix
    var expression, identifier;
    while (true) {
      if (Punctuator === token.type) {
        switch (token.value) {
          case '[':
            pushLocation(marker);
            next();
            expression = parseExpectedExpression();
            expect(']');
            base = finishNode(ast.indexExpression(base, expression));
            break;
          case '.':
            pushLocation(marker);
            next();
            identifier = parseIdentifier();
            base = finishNode(ast.memberExpression(base, '.', identifier));
            break;
          case ':':
            pushLocation(marker);
            next();
            identifier = parseIdentifier();
            base = finishNode(ast.memberExpression(base, ':', identifier));
            // Once a : is found, this has to be a CallExpression, otherwise
            // throw an error.
            pushLocation(marker);
            base = parseCallExpression(base);
            break;
          case '(': case '{': // args
            pushLocation(marker);
            base = parseCallExpression(base);
            break;
          default:
            return base;
        }
      } else if (StringLiteral === token.type) {
        pushLocation(marker);
        base = parseCallExpression(base);
      } else {
        break;
      }
    }

    return base;
  }

  //     args ::= '(' [explist] ')' | tableconstructor | String

  function parseCallExpression(base) {
    if (Punctuator === token.type) {
      switch (token.value) {
        case '(':
          if (!features.emptyStatement) {
            if (token.line !== previousToken.line)
              raise({}, errors.ambiguousSyntax, token.value);
          }
          next();

          // List of expressions
          var expressions = [];
          var expression = parseExpression();
          if (null != expression) expressions.push(expression);
          while (consume(',')) {
            expression = parseExpectedExpression();
            expressions.push(expression);
          }

          expect(')');
          return finishNode(ast.callExpression(base, expressions));

        case '{':
          markLocation();
          next();
          var table = parseTableConstructor();
          return finishNode(ast.tableCallExpression(base, table));
      }
    } else if (StringLiteral === token.type) {
      return finishNode(ast.stringCallExpression(base, parsePrimaryExpression()));
    }

    raiseUnexpectedToken('function arguments', token);
  }

  //     primary ::= String | Numeric | nil | true | false
  //          | functiondef | tableconstructor | '...'

  function parsePrimaryExpression() {
    var literals = StringLiteral | NumericLiteral | BooleanLiteral | NilLiteral | VarargLiteral
      , value = token.value
      , type = token.type
      , marker;

    if (trackLocations) marker = createLocationMarker();

    if (type & literals) {
      pushLocation(marker);
      var raw = input.slice(token.range[0], token.range[1]);
      next();
      return finishNode(ast.literal(type, value, raw));
    } else if (Keyword === type && 'function' === value) {
      pushLocation(marker);
      next();
      if (options.scope) createScope();
      return parseFunctionDeclaration(null);
    } else if (consume('{')) {
      pushLocation(marker);
      return parseTableConstructor();
    }
  }

  // Parser
  // ------

  // Export the main parser.
  //
  //   - `wait` Hold parsing until end() is called. Defaults to false
  //   - `comments` Store comments. Defaults to true.
  //   - `scope` Track identifier scope. Defaults to false.
  //   - `locations` Store location information. Defaults to false.
  //   - `ranges` Store the start and end character locations. Defaults to
  //     false.
  //   - `onCreateNode` Callback which will be invoked when a syntax node is
  //     created.
  //   - `onCreateScope` Callback which will be invoked when a new scope is
  //     created.
  //   - `onDestroyScope` Callback which will be invoked when the current scope
  //     is destroyed.
  //
  // Example:
  //
  //     var parser = require('luaparser');
  //     parser.parse('i = 0');

  exports.parse = parse;

  var versionFeatures = {
    '5.1': {
    },
    '5.2': {
      labels: true,
      emptyStatement: true,
      hexEscapes: true,
      skipWhitespaceEscape: true,
      strictEscapes: true
    },
    '5.3': {
      labels: true,
      emptyStatement: true,
      hexEscapes: true,
      skipWhitespaceEscape: true,
      strictEscapes: true,
      unicodeEscapes: true,
      bitwiseOperators: true,
      integerDivision: true
    },
    'LuaJIT': {
      // XXX: LuaJIT language features may depend on compilation options; may need to
      // rethink how to handle this. Specifically, there is a LUAJIT_ENABLE_LUA52COMPAT
      // that removes contextual goto. Maybe add 'LuaJIT-5.2compat' as well?
      labels: true,
      contextualGoto: true,
      hexEscapes: true,
      skipWhitespaceEscape: true,
      strictEscapes: true,
      unicodeEscapes: true
    }
  };

  function parse(_input, _options) {
    if ('undefined' === typeof _options && 'object' === typeof _input) {
      _options = _input;
      _input = undefined;
    }
    if (!_options) _options = {};

    input = _input || '';
    options = extend(defaultOptions, _options);

    // Rewind the lexer
    index = 0;
    line = 1;
    lineStart = 0;
    length = input.length;
    // When tracking identifier scope, initialize with an empty scope.
    scopes = [[]];
    scopeDepth = 0;
    globals = [];
    locations = [];

    if (!(features = versionFeatures[options.luaVersion])) {
      throw new Error(sprintf("Lua version '%1' not supported", options.luaVersion));
    }

    if (options.comments) comments = [];
    if (!options.wait) return end();
    return exports;
  }

  // Write to the source code buffer without beginning the parse.
  exports.write = write;

  function write(_input) {
    input += String(_input);
    length = input.length;
    return exports;
  }

  // Send an EOF and begin parsing.
  exports.end = end;

  function end(_input) {
    if ('undefined' !== typeof _input) write(_input);

    // Ignore shebangs.
    if (input && input.substr(0, 2) === '#!') input = input.replace(/^.*/, function (line) {
      return line.replace(/./g, ' ');
    });

    length = input.length;
    trackLocations = options.locations || options.ranges;
    // Initialize with a lookahead token.
    lookahead = lex();

    var chunk = parseChunk();
    if (options.comments) chunk.comments = comments;
    if (options.scope) chunk.globals = globals;

    /* istanbul ignore if */
    if (locations.length > 0)
      throw new Error('Location tracking failed. This is most likely a bug in luaparse');

    return chunk;
  }

}));
/* vim: set sw=2 ts=2 et tw=79 : */
/*! https://mths.be/luamin v1.0.4 by @mathias */
;(function(root) {

    // Detect free variables `exports`
    var freeExports = typeof exports == 'object' && exports;

    // Detect free variable `module`
    var freeModule = typeof module == 'object' && module &&
        module.exports == freeExports && module;

    // Detect free variable `global`, from Node.js or Browserified code,
    // and use it as `root`
    var freeGlobal = typeof global == 'object' && global;
    if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
        root = freeGlobal;
    }

    /*--------------------------------------------------------------------------*/

    var luaparse = root.luaparse || require('luaparse');
    luaparse.defaultOptions.comments = false;
    luaparse.defaultOptions.scope = true;
    var parse = luaparse.parse;

    var regexAlphaUnderscore = /[a-zA-Z_]/;
    var regexAlphaNumUnderscore = /[a-zA-Z0-9_]/;
    var regexDigits = /[0-9]/;

    // http://www.lua.org/manual/5.2/manual.html#3.4.7
    // http://www.lua.org/source/5.2/lparser.c.html#priority
    var PRECEDENCE = {
        'or': 1,
        'and': 2,
        '<': 3, '>': 3, '<=': 3, '>=': 3, '~=': 3, '==': 3,
        '..': 5,
        '+': 6, '-': 6, // binary -
        '*': 7, '/': 7, '%': 7,
        'unarynot': 8, 'unary#': 8, 'unary-': 8, // unary -
        '^': 10
    };

    var IDENTIFIER_PARTS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
        'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
        'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E',
        'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
        'U', 'V', 'W', 'X', 'Y', 'Z', '_'];
    var IDENTIFIER_PARTS_MAX = IDENTIFIER_PARTS.length - 1;

    var each = function(array, fn) {
        var index = -1;
        var length = array.length;
        var max = length - 1;
        while (++index < length) {
            fn(array[index], index < max);
        }
    };

    var indexOf = function(array, value) {
        var index = -1;
        var length = array.length;
        while (++index < length) {
            if (array[index] == value) {
                return index;
            }
        }
    };

    var hasOwnProperty = {}.hasOwnProperty;
    var extend = function(destination, source) {
        var key;
        if (source) {
            for (key in source) {
                if (hasOwnProperty.call(source, key)) {
                    destination[key] = source[key];
                }
            }
        }
        return destination;
    };

    var generateZeroes = function(length) {
        var zero = '0';
        var result = '';
        if (length < 1) {
            return result;
        }
        if (length == 1) {
            return zero;
        }
        while (length) {
            if (length & 1) {
                result += zero;
            }
            if (length >>= 1) {
                zero += zero;
            }
        }
        return result;
    };

    // http://www.lua.org/manual/5.2/manual.html#3.1
    function isKeyword(id) {
        switch (id.length) {
            case 2:
                return 'do' == id || 'if' == id || 'in' == id || 'or' == id;
            case 3:
                return 'and' == id || 'end' == id || 'for' == id || 'nil' == id ||
                    'not' == id;
            case 4:
                return 'else' == id || 'goto' == id || 'then' == id || 'true' == id;
            case 5:
                return 'break' == id || 'false' == id || 'local' == id ||
                    'until' == id || 'while' == id;
            case 6:
                return 'elseif' == id || 'repeat' == id || 'return' == id;
            case 8:
                return 'function' == id;
        }
        return false;
    }

    var currentIdentifier;
    var identifierMap;
    var identifiersInUse;
    var generateIdentifier = function(originalName) {
        // Preserve `self` in methods
        if (originalName == 'self') {
            return originalName;
        }

        if (hasOwnProperty.call(identifierMap, originalName)) {
            return identifierMap[originalName];
        }
        var length = currentIdentifier.length;
        var position = length - 1;
        var character;
        var index;
        while (position >= 0) {
            character = currentIdentifier.charAt(position);
            index = indexOf(IDENTIFIER_PARTS, character);
            if (index != IDENTIFIER_PARTS_MAX) {
                currentIdentifier = currentIdentifier.substring(0, position) +
                    IDENTIFIER_PARTS[index + 1] + generateZeroes(length - (position + 1));
                if (
                    isKeyword(currentIdentifier) ||
                    indexOf(identifiersInUse, currentIdentifier) > -1
                ) {
                    return generateIdentifier(originalName);
                }
                identifierMap[originalName] = currentIdentifier;
                return currentIdentifier;
            }
            --position;
        }
        currentIdentifier = 'a' + generateZeroes(length);
        if (indexOf(identifiersInUse, currentIdentifier) > -1) {
            return generateIdentifier(originalName);
        }
        identifierMap[originalName] = currentIdentifier;
        return currentIdentifier;
    };

    /*--------------------------------------------------------------------------*/

    var joinStatements = function(a, b, separator) {
        separator || (separator = ' ');

        var lastCharA = a.slice(-1);
        var firstCharB = b.charAt(0);

        if (lastCharA == '' || firstCharB == '') {
            return a + b;
        }
        if (regexAlphaUnderscore.test(lastCharA)) {
            if (regexAlphaNumUnderscore.test(firstCharB)) {
                // e.g. `while` + `1`
                // e.g. `local a` + `local b`
                return a + separator + b;
            } else {
                // e.g. `not` + `(2>3 or 3<2)`
                // e.g. `x` + `^`
                return a + b;
            }
        }
        if (regexDigits.test(lastCharA)) {
            if (
                firstCharB == '(' ||
                !(firstCharB == '.' ||
                regexAlphaUnderscore.test(firstCharB))
            ) {
                // e.g. `1` + `+`
                // e.g. `1` + `==`
                return a + b;
            } else {
                // e.g. `1` + `..`
                // e.g. `1` + `and`
                return a + separator + b;
            }
        }
        if (lastCharA == firstCharB && lastCharA == '-') {
            // e.g. `1-` + `-2`
            return a + separator + b;
        }
        var secondLastCharA = a.slice(-2, -1);
        if (lastCharA == '.' && secondLastCharA != '.' && regexAlphaNumUnderscore.test(firstCharB)) {
            // e.g. `1.` + `print`
            return a + separator + b;
        }
        return a + b;
    };

    var formatBase = function(base) {
        var result = '';
        var type = base.type;
        var needsParens = base.inParens && (
            type == 'BinaryExpression' ||
            type == 'FunctionDeclaration' ||
            type == 'TableConstructorExpression' ||
            type == 'LogicalExpression' ||
            type == 'StringLiteral'
        );
        if (needsParens) {
            result += '(';
        }
        result += formatExpression(base);
        if (needsParens) {
            result += ')';
        }
        return result;
    };

    var formatExpression = function(expression, options) {

        options = extend({
            'precedence': 0,
            'preserveIdentifiers': false
        }, options);

        var result = '';
        var currentPrecedence;
        var associativity;
        var operator;

        var expressionType = expression.type;

        if (expressionType == 'Identifier') {

            result = expression.isLocal && !options.preserveIdentifiers
                ? generateIdentifier(expression.name)
                : expression.name;

        } else if (
            expressionType == 'StringLiteral' ||
            expressionType == 'NumericLiteral' ||
            expressionType == 'BooleanLiteral' ||
            expressionType == 'NilLiteral' ||
            expressionType == 'VarargLiteral'
        ) {

            result = expression.raw;

        } else if (
            expressionType == 'LogicalExpression' ||
            expressionType == 'BinaryExpression'
        ) {

            // If an expression with precedence x
            // contains an expression with precedence < x,
            // the inner expression must be wrapped in parens.
            operator = expression.operator;
            currentPrecedence = PRECEDENCE[operator];
            associativity = 'left';

            result = formatExpression(expression.left, {
                'precedence': currentPrecedence,
                'direction': 'left',
                'parent': operator
            });
            result = joinStatements(result, operator);
            result = joinStatements(result, formatExpression(expression.right, {
                'precedence': currentPrecedence,
                'direction': 'right',
                'parent': operator
            }));

            if (operator == '^' || operator == '..') {
                associativity = "right";
            }

            if (
                currentPrecedence < options.precedence ||
                (
                    currentPrecedence == options.precedence &&
                    associativity != options.direction &&
                    options.parent != '+' &&
                    !(options.parent == '*' && (operator == '/' || operator == '*'))
                )
            ) {
                // The most simple case here is that of
                // protecting the parentheses on the RHS of
                // `1 - (2 - 3)` but deleting them from `(1 - 2) - 3`.
                // This is generally the right thing to do. The
                // semantics of `+` are special however: `1 + (2 - 3)`
                // == `1 + 2 - 3`. `-` and `+` are the only two operators
                // who share their precedence level. `*` also can
                // commute in such a way with `/`, but not with `%`
                // (all three share a precedence). So we test for
                // all of these conditions and avoid emitting
                // parentheses in the cases where we don’t have to.
                result = '(' + result + ')';
            }

        } else if (expressionType == 'UnaryExpression') {

            operator = expression.operator;
            currentPrecedence = PRECEDENCE['unary' + operator];

            result = joinStatements(
                operator,
                formatExpression(expression.argument, {
                    'precedence': currentPrecedence
                })
            );

            if (
                currentPrecedence < options.precedence &&
                // In principle, we should parenthesize the RHS of an
                // expression like `3^-2`, because `^` has higher precedence
                // than unary `-` according to the manual. But that is
                // misleading on the RHS of `^`, since the parser will
                // always try to find a unary operator regardless of
                // precedence.
                !(
                    (options.parent == '^') &&
                    options.direction == 'right'
                )
            ) {
                result = '(' + result + ')';
            }

        } else if (expressionType == 'CallExpression') {

            result = formatBase(expression.base) + '(';

            each(expression.arguments, function(argument, needsComma) {
                result += formatExpression(argument);
                if (needsComma) {
                    result += ',';
                }
            });
            result += ')';

        } else if (expressionType == 'TableCallExpression') {

            result = formatExpression(expression.base) +
                formatExpression(expression.arguments);

        } else if (expressionType == 'StringCallExpression') {

            result = formatExpression(expression.base) +
                formatExpression(expression.argument);

        } else if (expressionType == 'IndexExpression') {

            result = formatBase(expression.base) + '[' +
                formatExpression(expression.index) + ']';

        } else if (expressionType == 'MemberExpression') {

            result = formatBase(expression.base) + expression.indexer +
                formatExpression(expression.identifier, {
                    'preserveIdentifiers': true
                });

        } else if (expressionType == 'FunctionDeclaration') {

            result = 'function(';
            if (expression.parameters.length) {
                each(expression.parameters, function(parameter, needsComma) {
                    // `Identifier`s have a `name`, `VarargLiteral`s have a `value`
                    result += parameter.name
                        ? generateIdentifier(parameter.name)
                        : parameter.value;
                    if (needsComma) {
                        result += ',';
                    }
                });
            }
            result += ')';
            result = joinStatements(result, formatStatementList(expression.body));
            result = joinStatements(result, 'end');

        } else if (expressionType == 'TableConstructorExpression') {

            result = '{';

            each(expression.fields, function(field, needsComma) {
                if (field.type == 'TableKey') {
                    result += '[' + formatExpression(field.key) + ']=' +
                        formatExpression(field.value);
                } else if (field.type == 'TableValue') {
                    result += formatExpression(field.value);
                } else { // at this point, `field.type == 'TableKeyString'`
                    result += formatExpression(field.key, {
                        // TODO: keep track of nested scopes (#18)
                        'preserveIdentifiers': true
                    }) + '=' + formatExpression(field.value);
                }
                if (needsComma) {
                    result += ',';
                }
            });

            result += '}';

        } else {

            throw TypeError('Unknown expression type: `' + expressionType + '`');

        }

        return result;
    };

    var formatStatementList = function(body) {
        var result = '';
        each(body, function(statement) {
            result = joinStatements(result, formatStatement(statement), ';');
        });
        return result;
    };

    var formatStatement = function(statement) {
        var result = '';
        var statementType = statement.type;

        if (statementType == 'AssignmentStatement') {

            // left-hand side
            each(statement.variables, function(variable, needsComma) {
                result += formatExpression(variable);
                if (needsComma) {
                    result += ',';
                }
            });

            // right-hand side
            result += '=';
            each(statement.init, function(init, needsComma) {
                result += formatExpression(init);
                if (needsComma) {
                    result += ',';
                }
            });

        } else if (statementType == 'LocalStatement') {

            result = 'local ';

            // left-hand side
            each(statement.variables, function(variable, needsComma) {
                // Variables in a `LocalStatement` are always local, duh
                result += generateIdentifier(variable.name);
                if (needsComma) {
                    result += ',';
                }
            });

            // right-hand side
            if (statement.init.length) {
                result += '=';
                each(statement.init, function(init, needsComma) {
                    result += formatExpression(init);
                    if (needsComma) {
                        result += ',';
                    }
                });
            }

        } else if (statementType == 'CallStatement') {

            result = formatExpression(statement.expression);

        } else if (statementType == 'IfStatement') {

            result = joinStatements(
                'if',
                formatExpression(statement.clauses[0].condition)
            );
            result = joinStatements(result, 'then');
            result = joinStatements(
                result,
                formatStatementList(statement.clauses[0].body)
            );
            each(statement.clauses.slice(1), function(clause) {
                if (clause.condition) {
                    result = joinStatements(result, 'elseif');
                    result = joinStatements(result, formatExpression(clause.condition));
                    result = joinStatements(result, 'then');
                } else {
                    result = joinStatements(result, 'else');
                }
                result = joinStatements(result, formatStatementList(clause.body));
            });
            result = joinStatements(result, 'end');

        } else if (statementType == 'WhileStatement') {

            result = joinStatements('while', formatExpression(statement.condition));
            result = joinStatements(result, 'do');
            result = joinStatements(result, formatStatementList(statement.body));
            result = joinStatements(result, 'end');

        } else if (statementType == 'DoStatement') {

            result = joinStatements('do', formatStatementList(statement.body));
            result = joinStatements(result, 'end');

        } else if (statementType == 'ReturnStatement') {

            result = 'return';

            each(statement.arguments, function(argument, needsComma) {
                result = joinStatements(result, formatExpression(argument));
                if (needsComma) {
                    result += ',';
                }
            });

        } else if (statementType == 'BreakStatement') {

            result = 'break';

        } else if (statementType == 'RepeatStatement') {

            result = joinStatements('repeat', formatStatementList(statement.body));
            result = joinStatements(result, 'until');
            result = joinStatements(result, formatExpression(statement.condition))

        } else if (statementType == 'FunctionDeclaration') {

            result = (statement.isLocal ? 'local ' : '') + 'function ';
            result += formatExpression(statement.identifier);
            result += '(';

            if (statement.parameters.length) {
                each(statement.parameters, function(parameter, needsComma) {
                    // `Identifier`s have a `name`, `VarargLiteral`s have a `value`
                    result += parameter.name
                        ? generateIdentifier(parameter.name)
                        : parameter.value;
                    if (needsComma) {
                        result += ',';
                    }
                });
            }

            result += ')';
            result = joinStatements(result, formatStatementList(statement.body));
            result = joinStatements(result, 'end');

        } else if (statementType == 'ForGenericStatement') {
            // see also `ForNumericStatement`

            result = 'for ';

            each(statement.variables, function(variable, needsComma) {
                // The variables in a `ForGenericStatement` are always local
                result += generateIdentifier(variable.name);
                if (needsComma) {
                    result += ',';
                }
            });

            result += ' in';

            each(statement.iterators, function(iterator, needsComma) {
                result = joinStatements(result, formatExpression(iterator));
                if (needsComma) {
                    result += ',';
                }
            });

            result = joinStatements(result, 'do');
            result = joinStatements(result, formatStatementList(statement.body));
            result = joinStatements(result, 'end');

        } else if (statementType == 'ForNumericStatement') {

            // The variables in a `ForNumericStatement` are always local
            result = 'for ' + generateIdentifier(statement.variable.name) + '=';
            result += formatExpression(statement.start) + ',' +
                formatExpression(statement.end);

            if (statement.step) {
                result += ',' + formatExpression(statement.step);
            }

            result = joinStatements(result, 'do');
            result = joinStatements(result, formatStatementList(statement.body));
            result = joinStatements(result, 'end');

        } else if (statementType == 'LabelStatement') {

            // The identifier names in a `LabelStatement` can safely be renamed
            result = '::' + generateIdentifier(statement.label.name) + '::';

        } else if (statementType == 'GotoStatement') {

            // The identifier names in a `GotoStatement` can safely be renamed
            result = 'goto ' + generateIdentifier(statement.label.name);

        } else {

            throw TypeError('Unknown statement type: `' + statementType + '`');

        }

        return result;
    };

    var minify = function(argument) {
        // `argument` can be a Lua code snippet (string)
        // or a luaparse-compatible AST (object)
        var ast = typeof argument == 'string'
            ? parse(argument)
            : argument;

        // (Re)set temporary identifier values
        identifierMap = {};
        identifiersInUse = [];
        // This is a shortcut to help generate the first identifier (`a`) faster
        currentIdentifier = '9';

        // Make sure global variable names aren't renamed
        if (ast.globals) {
            each(ast.globals, function(object) {
                var name = object.name;
                identifierMap[name] = name;
                identifiersInUse.push(name);
            });
        } else {
            throw Error('Missing required AST property: `globals`');
        }

        return formatStatementList(ast.body);
    };

    /*--------------------------------------------------------------------------*/

    window.luamin = {
        'version': '1.0.4',
        'minify': minify
    };

    // Some AMD build optimizers, like r.js, check for specific condition patterns
    // like the following:
    if (
        typeof define == 'function' &&
        typeof define.amd == 'object' &&
        define.amd
    ) {
        define(function() {
            return luamin;
        });
    }   else if (freeExports && !freeExports.nodeType) {
        if (freeModule) { // in Node.js or RingoJS v0.8.0+
            freeModule.exports = luamin;
        } else { // in Narwhal or RingoJS v0.7.0-
            extend(freeExports, luamin);
        }
    } else { // in Rhino or a web browser
        root.luamin = luamin;
    }

}(window));

var win=window,exports=exports||{};exports.app=this;exports.CONST={};exports.DATA={};exports.SYMBOL={};exports.LOCATION={};exports.MODULE={};exports.KANMENGOU_HTTP="";exports.createNamespace=function(a){exports[a]||(exports[a]={});return exports[a]};exports.isArray=function(){return"[object Array]"==Object.prototype.toString.call(data)};exports.isString=function(a){return"string"==typeof a&&a.constructor==String};
exports.YceToken=function(){this.a1=this.a0=null;this.a2=new Int32Array(60);this.d=[this];iI(this)};exports.YceToken.prototype.init=function(){return m(this)};exports.YceToken.prototype.translateForKeygen=function(){return l(this)};exports.YceToken.prototype.getKeyGenForACtrl=function(){return iH(this)};exports.YceToken.prototype.int_to_zigzag=function(a){return iA(this,a)};exports.YceToken.prototype.zigzag_to_int=function(a){return z(this,a)};
var aSlot=null,oSlot=0,nullArray=[null],nullObj={d:nullArray,o:0};function m(a){var b=a.a0,a=a.a1;console.log(""+b,""+a);return 0}
function l(a){var b=new Date,c="",d=+b.getTime(),e=JSON.stringify(d),d=e.split(""),f=e.length,f=d[0+((f>>0)+-1>>0>>0)>>0>>0>>0],d=+parseInt(""+f),h=+b.getMinutes(),f=a.a2[h>>0>>0]>>0,h=+b.getSeconds(),h=a.a2[(30<h?1:2)>>0]>>0,a=a.a2[d>>0>>0]>>0,b=JSON.stringify(+((f&255)<<24>>24)),b=c.concat(""+b),c=JSON.stringify(+((h&255)<<24>>24)),b=b.concat(""+c),c=JSON.stringify(+((a&255)<<24>>24)),b=b.concat(""+c),c=e.substring(6);return b.concat(""+c)}
function iI(a){a.a0="%c install keygen done. ";a.a1="font: 1em Arial, Tahoma, simsun ;background: #333; color: #FFF;";a.a2[0]=65;a.a2[1]=89;a.a2[2]=65;a.a2[3]=68;a.a2[4]=83;a.a2[5]=69;a.a2[6]=89;a.a2[7]=66;a.a2[8]=83;a.a2[9]=84;a.a2[10]=83;a.a2[11]=52;a.a2[12]=50;a.a2[13]=69;a.a2[14]=72;a.a2[15]=69;a.a2[16]=89;a.a2[17]=69;a.a2[18]=83;a.a2[19]=84;a.a2[20]=67;a.a2[21]=53;a.a2[22]=68;a.a2[23]=49;a.a2[24]=69;a.a2[25]=48;a.a2[26]=89;a.a2[27]=65;a.a2[28]=83;a.a2[29]=84;a.a2[30]=69;a.a2[31]=54;a.a2[32]=
65;a.a2[33]=83;a.a2[34]=65;a.a2[35]=51;a.a2[36]=89;a.a2[37]=75;a.a2[38]=83;a.a2[39]=84;a.a2[40]=69;a.a2[41]=55;a.a2[42]=65;a.a2[43]=56;a.a2[44]=67;a.a2[45]=69;a.a2[46]=89;a.a2[47]=79;a.a2[48]=83;a.a2[49]=65;a.a2[50]=69;a.a2[51]=56;a.a2[52]=65;a.a2[53]=80;a.a2[54]=66;a.a2[55]=69;a.a2[56]=89;a.a2[57]=70;a.a2[58]=69;a.a2[59]=70;m(a)}function iH(a){return l(a)}function iA(a,b){return(b<<1^b>>31)>>0}function z(a,b){return(b>>>1^0-(b&1)>>0)>>0}function r(){}
function u(a,b){var c=String(),d=a[b>>0>>0]&255;if(0===(d&255))return c;for(var e=0;!(d=String.fromCharCode(d<<24>>24>>0),c=c.concat(d),e=(e>>0)+1>>0,d=a[(b>>0)+(e>>0)>>0]&255,0===(d&255)););return c}function g(a,b){return""+u(a,b>>0)}
var N=[0],M=new Uint8Array([37,99,32,105,110,115,116,97,108,108,32,107,101,121,103,101,110,32,100,111,110,101,46,32,0]),K=new Uint8Array([102,111,110,116,58,32,49,101,109,32,65,114,105,97,108,44,32,84,97,104,111,109,97,44,32,115,105,109,115,117,110,32,59,98,97,99,107,103,114,111,117,110,100,58,32,35,51,51,51,59,32,99,111,108,111,114,58,32,35,70,70,70,59,0]);r();
(function(){var a=exports.createNamespace("plugin");a.PluginCore=function(){this.id=this.dealloc=this.version=this.init=null};a.initPlugins=[];a.RemovePlugin=function(b){for(var c in a.initPlugins)if(a.initPlugins[c]==b){a.initPlugins[c].dealloc();a.initPlugins[c]=null;var d=a.indexOf(a.initPlugins[c]);-1!=d&&a.initPlugins.splice(d,1)}};a.indexOf=function(b){for(var c=a.initPlugins,d=c.length,e=0;e<d;e++)if(c[e].id==b.id)return e;return-1};a.InItPlugin=function(){for(var b in a)if("InItPlugin"!=b&&
"ExternalPlugin"!=b&&"initPlugins"!=b&&"RemovePlugin"!=b){var c=new a[b];a.initPlugins.push(c);c.id=a.initPlugins.length-1;null!=c.init&&c.init(exports.invokeData)}};a.ExternalPlugin=function(a,c){this.procMessage=c.procMessage;this.sendMessage=function(c){c.from=a;exports.cls.sender.sendMessage(c)};this.getModuName=function(){return a};this.getModuleOwner=function(){return c};exports.MODULE[a]=this}})();
(function(){var a=exports.createNamespace("cls");a.StateMachine=function(a){var c=null,d=null;this.setCurrentState=function(a){c=a};this.setPreviousState=function(a){d=a};this.setStateCommand=function(c,d){if(c&&c.hasOwnProperty(d))c[d](a)};this.changeState=function(a){this.setPreviousState(c);this.setStateCommand(d,"exit");this.setCurrentState(a);this.setStateCommand(a,"enter")};this.changingState=function(a){this.changeState(a);this.update()};this.update=function(){this.setStateCommand(c,"execute")};
this.revertToPreState=function(){this.changeState(d)};this.getCurrState=function(){return c};this.getPreviousState=function(){return d}};a.State=function(){return{enter:null,exit:null,execute:null}}})();
(function(){var a=exports.createNamespace("cls");a.peekMessage=function(){return{msgId:0,all:0,to:null,from:null,data:null}};a.Sender=function(){this.getOneTarget=function(a){var c=exports.MODULE;return null==c?{procMessage:function(){console.log("undefined owner's call back")}}:c[a]};this.notifyByAll=function(a){var c=exports.MODULE,d;for(d in c)this.getOneTarget(d).procMessage(a)};this.notifyByOne=function(a,c){a?a.procMessage(c):console.log("[error]not find the target %s.please check the message target name",
a)};this.notifyByGroup=function(a){var c=a.to;if(exports.isArray(c))for(var d=c.length;0<=--d;)this.notifyByOne(this.getOneTarget(c[d]),a)};this.sendMessage=this.notifyOnsending=function(a){if(0!=a.all)return this.notifyByAll(a);exports.isString(a.to)?this.notifyByOne(this.getOneTarget(a.to),a):this.notifyByGroup(a)}};a.sender=new a.Sender;a.Module=function(b){this.fsm=null;this.sendMessage=function(c){c.from=b;a.sender.sendMessage(c)};this.getModuName=function(){return b};this.procMessage=function(){};
exports.MODULE[b]=this}})();
(function(){exports.ROUTING_MODULE="ROUTING_MODULE";exports.Routing=function(){this.add=function(a,b){-1==a.indexOf("#")&&"/"!=a&&(a="#"+a);exports.LOCATION[a]=b};this.get=function(a){-1==a.indexOf("#")&&"/"!=a&&(a="#"+a);(a=exports.LOCATION[a])||(a=exports.LOCATION["/"]);return a};this.jump=function(a,b,c){var d=this.get(a);if(d){var e=b,f="";b?exports.isString(b)?(e=exports.utils.getURIParam(b),f=b):(e=b,f=c?"":exports.utils.makeParamURI(e)):e={};b=window.MESSAGE;b(exports.ROUTING_MODULE,d.getModuName(),
e);var d=f,h=h||exports.app;"/"!==a?d?("?"!=d.charAt(0)&&(d="?"+d),h.location.hash=a+d):h.location.hash=a:h.location.hash="/"}};this.flush=function(){var a="",b="",c=c||exports.app;c.location.hash?(b=c.location.hash,c=b.indexOf("?"),"#"==b.charAt(0)&&(-1<c?(a=b.substring(1,c),b=b.substring(c,b.length),this.jump(a,b)):(a=b.substring(1,b.length),this.jump(a)))):this.jump("/")}};exports.routing=new exports.Routing})();
(function(){window.Message=window.MESSAGE=function(a,b,c,d){var e=exports.cls.peekMessage();a&&(e.msgId=a);b&&(e.to=b);c&&(e.data=c);d&&(e.all=d);e.all=0;exports.cls.sender.sendMessage(e)};window.App=window.APP=function(a,b,c){a&&b?(a=new a(b),c&&a.hasOwnProperty("procMessage")&&(a.procMessage=c)):console.log("params is error")}})();
var isInclude=!1,stdLibSymblos={include:function(a,b){var c=b[0].value;if(include_deps[c])return"-- already exists ";include_deps[c]={};include_deps[c].code=vfs.getFileContent(c);var d=c.substring(c.lastIndexOf("."),c.length);isInclude=!0;var e=exports.frontend.parse(include_deps[c].code,{attachComment:!0,range:!0,loc:!0,sourceType:"script",tolerant:!0,tokens:!1});exports.lexerGenerateCode(e);isInclude=!1;include_deps[c].code||(console.error("vfs error:not find file "+c),include_deps[c]=null);switch(d){case ".aop":return"-- include ";
default:return"--not define"}},"console.log":function(){return"print"},push:function(a,b){return"table.apush("+a+","+b.join(",")+")"},pop:function(a){return"table.apop("+a+")"},unshift:function(a,b){return"table.aunshift("+a+","+b.join(",")+")"},shift:function(a){return"table.ashift("+a+")"},splice:function(a,b){return"table.asplice("+a+","+b.join(",")+")"},slice:function(a,b){return"table.aslice("+a+","+b.join(",")+")"},concat:function(a,b){return"table.aconcat("+a+","+b.join(",")+")"},join:function(a,
b){return"table.ajoin("+a+","+b.join(",")+")"},eachIndex:function(a,b){return"table.eachIndex("+a+","+b.join(",")+")"},indexOf:function(a,b){return"table.aindexOf("+a+","+b.join(",")+")"},sort:function(a,b){return"table.asort("+a+","+b.join(",")+")"}},constructMethods=null,currClassName=null,classesSymblos={},depencies={},arraySymblos={},extensionSyntax={AOP:"AopStatement",BREAKPOINT:"BreakPointStatement"},stdLibProbs={length:function(a){return"table.alength("+a+")"}};
exports.AopStatement=function(a){aop_retval=null;var b=GetValueByType(a.callee),c=a.arguments,d=c.length,a=[];aop_method_hook=!0;aop_blocks=[];aop_params=[];for(var e=0;e<d;e++)a.push(GetValueByType(c[e]));stdLibSymblos[b]&&(b=stdLibSymblos[b](b));b=b.split(".");if(1<b.length&&stdLibSymblos[b[1]])return b=stdLibSymblos[b[1]](b[0],a);aop_method_hook=!1;if(3==a.length)switch(c=RegExp('"',"g"),b=a[0].replace(c,""),a=a[1].replace(c,""),b){case "breakpoint":aop_breakpoint[a]={},aop_breakpoint[a].type=
b,aop_breakpoint[a].code=aop_blocks,aop_breakpoint[a].params=aop_params,console.log("add breakpoint",aop_breakpoint[a])}return null};exports.BlockStatement=function(a){for(var a=a.body,b=a.length,c=[],d=0;d<b;d++)c[d]=GetValueByType(a[d]);return c.join("\n")};
exports.BreakPointStatement=function(a){aop_retval=[];for(var b=GetValueByType(a.callee),c=a.arguments,d=c.length,a=[],e=0;e<d;e++)a.push(GetValueByType(c[e]));stdLibSymblos[b]&&(b=stdLibSymblos[b](b));b=b.split(".");if(1<b.length&&stdLibSymblos[b[1]])return b=stdLibSymblos[b[1]](b[0],a);if(1<=a.length&&(b=a[0].replace(RegExp('"',"g"),""),aop_breakpoint[b])){b=aop_breakpoint[b];c=[];if(0<b.params.length){d=b.params.length;for(e=0;e<d;e++)c.push("local "+b.params[e]+"="+a[e+1]+"\n")}aop_blocks=b.code;
aop_retval=c.concat(aop_blocks)}return null};exports.BreakStatement=function(){return 0==exports.stack_switch.length?"\nbreak\n":"\n"};exports.CallExpression=function(a){for(var b=GetValueByType(a.callee),c=a.arguments,d=c.length,a=[],e=0;e<d;e++)a.push(GetValueByType(c[e]));stdLibSymblos[b]&&(b=stdLibSymblos[b](b,c));c=b.split(".");return 1<c.length&&stdLibSymblos[c[1]]?b=stdLibSymblos[c[1]](c[0],a):b+" ("+a.join(",")+")"};
exports.CatchClause=function(a){var b="";a.body&&(b=GetValueByType(a.body));var c="";a.param&&(c=GetValueByType(a.param));return" local  "+c+" = err \n"+b+"\n"};exports.ConditionalExpression=function(a){var b="";a.test&&(b=GetValueByType(a.test));var c;a.consequent&&(c=GetValueByType(a.consequent));var d;a.alternate&&(d=GetValueByType(a.alternate));return"("+b+" and "+c+" or "+d+")"};exports.ExpressionStatement=function(a){return GetValueByType(a.expression)};
exports.ForInStatement=function(a){var b=GetValueByType(a.left),c=GetValueByType(a.right),a=GetValueByType(a.body),d=[];d.push("for "+b+", v in pairs("+c+") do");d.push(a);d.push("end");return d.join("\n")};exports.ForStatement=function(a){var b=[],c=GetValueByType(a.init),d=GetValueByType(a.update),e=GetValueByType(a.test);b.push(c);b.push("\nwhile "+e+" do\n");b.push(GetValueByType(a.body));b.push("\n"+d+";\n");b.push("end\n");return b.join("")};
exports.FunctionExpression=function(a){var b=[],c=0;if(a.params){var d=a.params.length;if(0<d)for(var e=0;e<d;e++)b[e]=GetValueByType(a.params[e]);1==d&&"RestElement"==a.params[0].type&&(c=1,a.params[0]=a.params[0].argument.name)}if(a.id&&"__classMethod"==a.id&&a.methodName){if(a.methodName==currClassName)return constructMethods={},constructMethods.params=b,constructMethods.code=GetValueByType(a.body),"";b.unshift("self")}c?(c="function ("+b.join(",")+") \n",c+="local "+a.params[0]+"=arg or ...\n"):
c="function ("+b.join(",")+") \n";a.body&&(a=GetValueByType(a.body),aop_method_hook&&(aop_blocks.push(a),aop_params=b),c+=a);return c+"\nend\n"};exports.IfStatement=function(a){var b=[];if(a.test){var c=GetValueByType(a.test);b.push("\nif "+c+" then\n")}a.consequent&&b.push(GetValueByType(a.consequent));a.alternate&&(a="\n else \n"+GetValueByType(a.alternate),b.push(a));b.push("\nend\n");return b.join("")};exports.Literal=function(a){return a.raw};
exports.LogicalExpression=function(a){var b=GetValueByType(a.left);right=GetValueByType(a.right);switch(a.operator){case "&&":a.operator=" and ";break;case "||":a.operator=" or "}return b+a.operator+right};exports.MemberExpression=function(a){var b=GetValueByType(a.object),c=GetValueByType(a.property);return a.computed?b+"["+c+"]":stdLibProbs[c]?stdLibProbs[c](b):b+"."+c};
exports.SwitchCase=function(a){var b;a.test&&(b=GetValueByType(a.test),exports.test_switch.push(b));var c=[];if(a.consequent)for(var d=a.consequent,a=d.length,e=0;e<a;e++)c.push(GetValueByType(d[e]));d="";exports.stack_switch[0]||console.log("[error] switch stack error.");if(b){var f=exports.stack_switch.pop();exports.switches[b+""]=f;if(0==c.length)return exports.merge_switch.push(f),"";d=d+('exports["'+f+'"]=function ()\n')+c.join("\n");d+="end\n";if(0<exports.merge_switch.length){a=exports.merge_switch.length;
for(e=0;e<a;e++)d+='exports["'+exports.merge_switch[e]+'"]=exports["'+f+'"]\n';exports.merge_switch=[]}}else d+='exports["'+exports.defaultName+'"]=function ()\n',d+=c.join("\n"),d+="end\n";return d};
exports.SwitchStatement=function(a){var b="";exports.merge_switch=[];exports.test_switch=[];exports.switches={};exports.defaultName="";depencies["switch"]=!0;var c;a.discriminant&&(c=GetValueByType(a.discriminant),exports.stack_switch=[],exports.stack_switch.push(c));if(a.cases){var b=a.cases,a=b.length,d=getRandomName();exports.defaultName=d;for(var e=0;e<a;e++)exports.stack_switch.push(getRandomName());exports.switches['"default"']=d;d=[];for(e=0;e<a;e++)d[e]=GetValueByType(b[e])}e=getRandomName();
b="local exports=exports\n"+("local "+e+" = "+makeLuaTable(getRandomName(),exports.switches)+"\n");b+='if exports["'+exports.defaultName+'"] == nil then\n'+d.join("")+"\nend\n";a=exports.stack_switch.length;0!=a&&(b=b+("local __indexer__ = "+e+"["+c+"]\n")+("if __indexer__ == nil then \n __indexer__="+e+'["default"]')+"\nend\nif exports[__indexer__] ~= nil then \n exports[__indexer__]() \nend");0!=exports.stack_switch.length&&(exports.stack_switch=[]);return b};exports.ThisExpression=function(){return"self"};
exports.UnaryExpression=function(a){switch(a.operator){case "!":a.operator="not"}return a.operator+" "+GetValueByType(a.argument)};exports.UpdateExpression=function(a){var b=GetValueByType(a.argument);return"++"==a.operator?b+"="+b+"+1":b+"="+b+"-1"};
var isNumber=function(a){return!1==isNaN(Number(a))},isString=function(a){var b=a.indexOf('"'),a=a.lastIndexOf('"');return-1!=b&&-1!=a&&b!=a},getRandomName=function(){return"CODE"+((new Date).getTime()+"").substr(6,6)+(1E3*Math.random()>>0)+(1E3*Math.random()>>0)+(1E3*Math.random()>>0)+(1E3*Math.random()>>0)+(15<30*Math.random()?"H":"L")},makeLuaTable=function(a,b){var c=[],d;for(d in b)c.push("["+d+']="'+b[d]+'"');return"{\n"+c.join(",\n")+"\n}"},decodeSecurity=function(a){for(var b=a.length,c=0;c<
b;c++)a[c]=255-a[c]>>0;for(var a=new Uint8Array(a),b=a.byteLength,d="",c=0;c<b;){var e=a[c];128>e?(d+=String.fromCharCode(e),c++):191<e&&224>e&&c+1<b?(d+=String.fromCharCode((e&31)<<6|a[c+1]&63),c+=2):c+2<b&&(d+=String.fromCharCode((e&15)<<12|(a[c+1]&63)<<6|a[c+2]&63),c+=3)}return d};exports.WhileStatement=function(a){var b=[];if(a.test){var c=GetValueByType(a.test);b.push("while "+c+" do \n")}a.body&&b.push(GetValueByType(a.body));b.push("\nend\n");return b.join("")};
exports.ArrayExpression=function(a){var b=0;depencies.array=!0;if(a&&a.elements){var c=a.elements.length;if(0==c)return"{}";if(1==c){console.log("extern syntax");var d=a.elements[0];"CallExpression"==d.type&&extensionSyntax[d.callee.name]&&(d.type=extensionSyntax[d.callee.name],b=1)}for(var d=[],e=0;e<c;e++)d.push(GetValueByType(a.elements[e]));c=d.length;a=[];for(e=1;e<=c;e++)a[e]=1==e?"["+e+"]="+d[e-1]:"\n["+e+"]="+d[e-1];a.shift();return 1==b?aop_retval?aop_retval.join(""):"":"{"+a.join(",")+"}"}return"null"};
exports.AssignmentExpression=function(a){var b=GetValueByType(a.left),c=GetValueByType(a.right);switch(a.operator){case "+=":return b+"="+b+"+"+c;case "-=":return b+"="+b+"-"+c;case "*=":return b+"="+b+"*"+c;case "/=":return b+"="+b+"/"+c;case "%=":return b+"="+b+"%"+c;case "=":arraySymblos[b]=arraySymblos[c]&&-1==c.indexOf('"')?1:0}return b+a.operator+c};
exports.BinaryExpression=function(a){var b=GetValueByType(a.left),c=GetValueByType(a.right);switch(a.operator){case "!=":a.operator="~=";break;case "+":var d=isString(b),e=isString(c);if("Identifier"==a.left.type)a.operator="..",arraySymblos[b]&&arraySymblos[c]&&(a.operator="+",arraySymblos[b]=1);else if("Identifier"==a.right.type)a.operator="..",arraySymblos[c]&&(a.operator="+",arraySymblos[c]=1);else if(d||e)a.operator="..";break;case "-":case "*":case "/":case "%":"Identifier"==a.right.type?arraySymblos[b]=
1:arraySymblos[c]=1;arraySymblos[b+a.operator+c]=1;break;case ">>>":if(d=isNumber(c))break;RegExp("New[ (]+","g").test(c)&&(c=c.replace("New","new"));a.operator=":"}"null"==c&&(c="nil");return b+a.operator+c};exports.ClassBody=function(a){if(a=a.body){for(var b=a.length,c=[],d=0;d<b;d++)c[d]=GetValueByType(a[d]);return c.join("\n")}};
exports.ClassDeclaration=function(a){var b=GetValueByType(a.id);currClassName=b;classesSymblos[b]&&console.log("alerdy define classed.");var c=GetValueByType(a.superClass);if(c==b)console.log("error::class can't self examination");else{if(a.body)var d=GetValueByType(a.body);a=c?"local "+b+"="+c+":new()\n":"local "+b+"={}\n";a=constructMethods?a+("function "+b+":new("+constructMethods.params.join(",")+")\n"):a+("function "+b+":new(o)\n");a+="local o=o or {}\nsetmetatable(o,self)\n";constructMethods&&
(a+=constructMethods.code+"\n");currClassName=constructMethods=null;return a+"self.__index= self\nreturn o\nend\n\n"+('window.registerStd (0, "'+b+'", '+b+")\n")+d}};exports.FunctionDeclaration=function(a){var b=[],c=GetValueByType(a.id);if(a.params){var d=a.params.length;if(0<d)for(var e=0;e<d;e++)b[e]=GetValueByType(a.params[e])}b="local "+c+"=function ("+b.join(",")+")  \n";a.body&&(b+=GetValueByType(a.body));return b+"\nend\n"};exports.Identifier=function(a){return a.name};
exports.MethodDefinition=function(a){var b=GetValueByType(a.key),c=Number(a["static"])>>0;a.value.id="__classMethod";a.value.methodName=b;1==c&&(a.value.id="__classStaticMethod");a=GetValueByType(a.value);return currClassName==b?"":currClassName+"."+b+" ="+a};
exports.ObjectExpression=function(a){var b=a.properties;if(0==b.length)return"{}";for(var c=b.length,a=[],d=0;d<c;d++)a.push(GetValueByType(b[d].key)),a.push(GetValueByType(b[d].value));for(b=[];0==!a.length;)c=a.shift(),d=a.shift(),c&&(-1==c.indexOf('"')?b.push('["'+c+'"] = '+d):b.push("["+c+"] = "+d));return"{\n"+b.join(",\n")+"\n}"};exports.Property=function(a){return exports.GetValueByType(a.value)};exports.RestElement=function(){return"..."};
exports.ReturnStatement=function(a){return(a=GetValueByType(a.argument))?"\nreturn "+a+"\n":"\nreturn\n"};exports.TryStatement=function(a){var b="";a.block&&(b=GetValueByType(a.block));var c="";a.handler&&(c=GetValueByType(a.handler));var d="";a.finalizer&&(d=GetValueByType(a.finalizer));return"local status,err = pcall (function()\n"+b+"\nend)\n if err ~= nill then \n"+c+"end \n"+d+"\n"};
exports.VariableDeclaration=function(a){for(var a=a.declarations,b=a.length,c=[],d=0;d<b;d++)c[d]=GetValueByType(a[d]),1<b&&(c[d]=c[d].replace("local",""));return 1<b?"local "+c.join(","):c[0]};exports.VariableDeclarator=function(a){var b=a.init,a=GetValueByType(a.id);return(b=GetValueByType(b))?(isNumber(b)&&(arraySymblos[a]=1),arraySymblos[b]&&(arraySymblos[a]=1),"local "+a+"="+b):a};
var aop_method_hook=!1,aop_blocks=[],aop_params=[],aop_inlines={},aop_symblos={},aop_breakpoint={},aop_retval=null,include_deps=[],require_deps=[],dom={addEventListener:function(a,b,c){$(a).on(b,lstate_lua_callback(c))},removeEventListener:function(a,b){$(a).off(b)},find:function(a){return $(a)},setText:function(a,b){$(a).text(b)},setHtml:function(a,b){$(a).html(b)},tml:function(a,b){return Tml(a,b)},time:function(){console.time("t")},timeEnd:function(){console.timeEnd("t")}};
exports.Main=function(a){console.log("lua mode.");if(-1!=a.indexOf("new("))console.log("error::syntax new syntax must be use New syntax");else{window.macroRender&&(a=window.macroRender(a,window.macros));var b={attachComment:!1,range:!1,loc:!1,sourceType:"script",tolerant:!0,tokens:!1},b=exports.frontend.parse(a,b),b={attachComment:!1,range:!1,loc:!1,sourceType:"script",tolerant:!0,tokens:!1},b=exports.frontend.parse(a,b);return exports.lexerGenerateCode(b)}};var gen_codes=[];
exports.lexerGenerateCode=function(a){var a=a.body,b=a.length;gen_codes=[];for(var c=0;c<b;c++)gen_codes[c]=GetValueByType(a[c]),console.log("%d : %s",c+1,gen_codes[c]);if(!isInclude){a=gen_codes.join("\n");depencies["switch"]&&(gen_codes.unshift("local exports={}"),depencies["switch"]=null);-1!=a.indexOf("Math.")&&gen_codes.unshift('local Math  = require("core/math")');depencies.array&&(gen_codes.unshift('local table = require("core/array")'),depencies.array=null);for(var d in depencies)depencies[d]&&
gen_codes.unshift('require("'+d+'")')}depencies={};arraySymblos={};classesSymblos={};return gen_codes.join("\n")};var GetValueByType=function(a){return null==a?null:!a.type?(console.log("type %s is not implements",type),"not implements "+type):exports[a.type]?exports[a.type](a):null};setTimeout(function(){vfs&&vfs.mount("stdlib.rsl",function(a){"stdlib.rsl"==a&&((a=vfs.getFileContent("core/def"))&&L.execute(a),(a=vfs.getFileContent("core/require"))&&L.execute(a))})},50);
function registerStd(a,b){L._G.set(a,b)}var tmlCache={},keyMaxsize=16;function getCacheKey(a){var b=a.length,c="";b>keyMaxsize?(c=a.substring(0,keyMaxsize-(b+"").length),c+=a.charAt(b),c+=b):c=a;return btoa(c)}function Tml(a,b){var c=getCacheKey(a),d=tmlCache[c];d?symblos=d.symblos:(symblos=getSymblos(a,c),d=tmlCache[c]);return replaceAll(symblos,a,b,d.regexps)}function replaceAll(a,b,c,d){for(var e in a)b=c[e]?b.replace(d[e],c[e]):b.replace(d[e],"null");return b}
function getSymblos(a,b){for(var c=a.length,d={},e,f="",h=[],k={},j=0,i=0;j<c;j++)f=a.charAt(j),"{"==f?(h.push(1),e=""):("}"==f&&(i=h.pop(),!d[e]&&i&&(d[e]=1,k[e]=RegExp("{"+e+"}","g")),e=""),e+=f);tmlCache[b]={};tmlCache[b].symblos=d;tmlCache[b].regexps=k;return d}
(function(){var a=exports.createNamespace("cls"),b=b||{};a.Keygen=new exports.YceToken;a.xhrs=[function(){return new XMLHttpRequest},function(){return new b("Microsoft.XMLHTTP")},function(){return new b("MSXML2.XMLHTTP.3.0")},function(){return new b("MSXML2.XMLHTTP")}];a.Raw=function(){for(var b=0,d=a.xhrs.length;b<d;b++)try{var e=(0,a.xhrs[b])();if(null!=e)return e}catch(f){}return{}};a.RawRequest=a.getRaw;a.DATA_TYPE_TEXT="text";a.DATA_TYPE_BINARY="arrayBuffer";a.defufaultConfig={timeOut:3E3,userAgent:"URLRequest",
lang:"en",type:"GET",contentType:"application/x-www-form-urlencoded",dataType:a.DATA_TYPE_TEXT,processData:!0,headers:{},cache:!0,env:"publish"};a.makeParamURI=function(a){var b=[],e=/%20/g,f;for(f in a)b.push(encodeURIComponent(f).replace(e,"+")+"="+encodeURIComponent(a[f]+"").replace(e,"+"));return b.join("&")};a.decodeDataType=function(a){var b=null;switch(a.type){case "json":b=window.JSON?JSON.parse(a.responseText):eval(a.responseText);break;case "script":b=eval(a.responseText);break;case "xml":b=
a.responseXML;break;default:b=a.responseText}return b};a.Timer=function(a,b){this.ticks=a;this.handle=b;this.maxnum=36E5;this.currTick=this.pid=0;this.reset=function(){this.stop();this.start()};this.stop=function(){clearTimeout(this.pid);this.currTick=this.ticks=0};var e=this.count=function(a){a.maxnum<=a.currTick&&(a.currTick=0);a.currTick+=a.ticks;clearTimeout(a.pid);a.handle(a);0!=a.ticks&&(a.pid=setTimeout(function(){e(a)},a.ticks))};this.start=function(){this.count(this)}};a.Epoll=function(){this.cirQueue=
[];this.offset=0;this.add=function(a){this.cirQueue[this.offset]=a;this.offset++};this.del=function(a){a=this.eachIdx(a);0<=a&&this.cirQueue.splice(a,1);this.offset--};this.eachIdx=function(a){for(var b=this.cirQueue,e=0;e<this.offset;e++)if(b[e].key==a.key)return e;return-1};this.chk=function(){var a=this.cirQueue,b;for(b in a)if(0!=a[b].starttime)if(1==a[b].isdone)this.del(a[b]);else if(a[b].isdone||(a[b].endtime=(new Date).getSeconds()),1E3*(a[b].endtime-a[b].starttime+1)>a[b].timeout)a[b].hasOwnProperty("dealloc")&&
a[b].dealloc(),this.del(a[b])}};a.epoll=new a.Epoll;a.indexOf=function(a,b){for(var e=a.length,f=0;f<e;f++)if(a[f].src&&a[f].src==b.src)return f;return-1};a.CrossDomainRequest=function(b,d,e){this.data=b.data;this.key=e;this.script=document.createElement("script");this.script.type="text/javascript";this.script.async=!0;this.callback=1==b.callback?"q"+(1E3*Math.random()>>0)+this.key:"callbackDisaster";this.timeout=b.timeout;this.starttime=(new Date).getSeconds();this.data=null;this.method=b.method;
this.dataType=b.dataType;this.crossdomain=!0;this.endtime=this.starttime;this.isdone=0;a.epoll.add(this);var f=document.head||document.getElementsByTagName("head")[0];f.appendChild(this.script);-1==b.url.indexOf("?")?-1==b.url.indexOf("callback")&&"callbackDisaster"!=this.callback&&(b.url+="?callback"+this.callback):-1==b.url.indexOf("callback")&&"callbackDisaster"!=this.callback&&(b.url+="&callback="+this.callback);this.script.src=b.url;console.log(this.script.src);var h=this;this.dealloc=function(){h.endtime=
(new Date).getSeconds();h.isdone=1;window[h.callback]=function(){}};this.onloaded=function(b){console.log(b,"loaded");d.success({target:h,data:b});h.endtime=(new Date).getSeconds();h.isdone=1;if(h.callback!="callbackDisaster"){f.removeChild(f.childNodes[a.indexOf(f.childNodes,h.script)]);delete window[h.callback]}};this.script.onerror=function(b){d.ioerror({target:this,data:b.toString()});f.removeChild(f.childNodes[a.indexOf(f.childNodes,h.script)]);delete window[this.callback]};window[this.callback]=
this.onloaded};a.EVENT_SUCCESS="success";a.EVENT_IOERROR="ioerror";a.EVENT_SUCCESS="diskerror";a.EVENT_TIMEOUT="timeout";a.URLRequest=function(b,d){this.timeout=a.defufaultConfig.timeout;this.starttime=0;this.data={};this.method="GET";this.raw=new a.Raw;this.dataType=a.defufaultConfig.dataType;this.url=b;this.headers=a.defufaultConfig.headers;this.type=a.defufaultConfig.type;this.crossdomain=!1;this.isdone=this.endtime=0;this.key=null;null==d&&(d={},d.success=d.diskerror=d.ioerror=console.log);this._handle=
d;this.setJSONData=function(a,b){if(this.url){var c=b;exports.isString(b)||(c=JSON.stringify(b));if(!this.data)this.data={};this.data[a]=c}};this.dealloc=function(){this.raw.close!=null&&this.raw.close()};this.doUpload=function(b,c){if(c)this._handle=c;if(this.url!=null){if(!this.data)this.data={};if(this.key==null)this.key=a.Keygen.translateForKeygen();this.endtime=this.starttime=(new Date).getSeconds();if(this.method=="GET"&&this.key!=null)this.url=this.url.indexOf("?")==-1?this.url+("?"+a.makeParamURI(this.data)+
"k="+this.key):this.url+("&"+a.makeParamURI(this.data)+"&k="+this.key);if(this.crossdomain){this.raw=new a.CrossDomainRequest(this,this._handle,this.key);if(this.ref)this.raw.ref=this.ref;this.raw.data=this.data}else{a.epoll.add(this);this.raw.method=this.method;this.raw.open(this.method,this.url,true);try{for(var d in this.headers)this.raw.setRequestHeader(d,this.headers[d])}catch(k){console.log(k,">>>>>>>");return}var j=this.raw,i=this;this.raw.onerror=function(a){i._handle.ioerror({traget:i,data:a.toString()});
i.endtime=(new Date).getSeconds();i.isdone=1};this.raw.onreadystatechange=function(){if(j.readyState==4)if(j.status<300){try{var b=a.decodeDataType(j)}catch(c){i._handle.diskerror!=null&&i._handle.diskerror({traget:i,data:j.statusText});return}if(i._handle.success!=null){i.endtime=(new Date).getSeconds();i.starttime=i.endtime;i.isdone=1;a.epoll.del(i);i._handle.success({target:i,data:b})}else console.log("error:not params entry.")}else i._handle.ioerror!=null&&i._handle.ioerror({target:i,data:j.statusText})};
if(this.method=="GET")this.raw.send(null);else{this.raw.setRequestHeader("Content-Type","application/x-www-form-urlencoded");this.raw.send(a.postDataFormat(this.data))}}}}};a.postDataFormat=function(a){var b=[],e=0,f;for(f in a)b[e]=encodeURIComponent(f)+"="+encodeURIComponent(a[f]),e++;return b.join("&")};a.URLLoader=function(){this.type="URLLoader";this.load=function(a,b){null!=a.doUpload&&(b?a.doUpload(this,b):a.doUpload(this))}}})();var vfs={};vfs.baseUrl=window.BaseURL;vfs.name="";vfs.data={};
vfs.rawNames={};vfs.trimURL=function(a){a||(a="null");return"."==a.charAt(0)&&"/"==a.charAt(1)?a.substring(2,a.legnth).replace("//","/"):a};vfs.events={};
vfs.mount=function(a,b){vfs.baseUrl=window.BaseURL;vfs.events[a]=b;var c=a,a=vfs.getBaseRemotingURL(a),d=vfs.getFileContent(c);if(d){var d=d.split("|"),e=d.length;if(d[e-1]==(new Date).toDateString()){for(var f=0;f<e;f++)vfs.rawNames[d[f]]=1;vfs.events[c](c);return}}setTimeout(function(){var b=new XMLHttpRequest;b.open("GET",a,!0);b.responseType="arraybuffer";b.onerror=function(){console.log(a)};b.onload=function(){var a=new Blob([b.response],{type:"image/png"}),a=URL.createObjectURL(a),d=new Image,
e=new PNGDrive;d.onload=function(){e.decode(d);for(var a=e.getFileAt(0),a=e.utf8Decode(a.content).split("--["),b=-1,f="",h=a.length,k=[],o=0;o<h;o++){var n=a[o];n&&(b=n.indexOf("]"),-1!=b&&(f=n.substring(0,b),k.push(f),vfs&&vfs.setFileContent(f,n.substring(b+1,n.length))))}vfs&&(vfs.setFileContent(c,k.join("|")+"|"+(new Date).toDateString()),vfs.events[c](c))};d.onerror=function(){console.log("not find std lib")};d.src=a};b.send()},0)};
vfs.getBaseRemotingURL=function(a){return!vfs.baseUrl?vfs.trimURL(a):vfs.baseUrl+"/"+vfs.trimURL(a)+"?__vfs__="+(1E4*Math.random()>>0)};vfs.getNormalisePath=function(a){return vfs.trimURL(a)};vfs.listFileNames=function(){var a=[],b;for(b in vfs.rawNames)a.push(b);return a};vfs.getFileContent=function(a){var a=vfs.getNormalisePath(a),b=vfs.data[a];if(!b)if(b=window.localStorage.getItem(a))vfs.data[a]=b;else return null;return b};
vfs.setFileContent=function(a,b){vfs.rawNames[a]=!0;var c=vfs.getNormalisePath(a);vfs.data[c]=b;window.localStorage.setItem(c,b)};function makeJSObject(){return{}}function makeCallBack(a){return function(b){window.callEx(a,b)}}function std_request(a,b){var c=new exports.cls.URLRequest(a,{success:makeCallBack(b),ioerror:function(a){console.log(a)}});c.method="GET";(new exports.cls.URLLoader).load(c)}var apolloxLua={parse:exports.Main};exports.mainEntry=function(){console.log("entry web mode.")};
!function(a,b,c){"undefined"!=typeof exports?"undefined"!=typeof module&&module.exports?module.exports=c():exports[a]=c():"function"==typeof define&&define.amd?define(c):b[a]=c();exports["frontend"]=c()}("Chiffon",this,function(){"use strict";function a(a){return new RegExp("(/[*][\\s\\S]*?[*]/|//[^"+D+"]*|<!--[^"+D+"]*|(?:^|"+E+")(?:"+F+")?-->[^"+D+"]*"+(a===u?"":"|"+J+G)+'|"(?:\\\\\\r\\n|\\\\[\\s\\S]|[^"'+D+"\\\\])*\"|'(?:\\\\\\r\\n|\\\\[\\s\\S]|[^'"+D+"\\\\])*'"+(a===x?"":"|"+I+G)+"|0(?:[xX][0-9a-fA-F]+|[oO][0-7]+|[bB][01]+)|(?:\\d+(?:[.]\\d*)?|[.]\\d+)(?:[eE][+-]?\\d+)?|[1-9]\\d*|0[0-7]+|"+H+(a===s?"":"|"+F)+"|"+E+"|"+(a===u?"[\\s\\S]":K)+")","g")}function b(a){return 65535>=a?q(a):(a-=65536,q((a>>10)+55296,a%1024+56320))}function c(a){return 10===a||13===a||8232===a||8233===a}function d(a){return!U.test(a)}function e(a){return a>=48&&57>=a}function f(a){var b=a.charCodeAt(0);return b>=48&&55>=b}function g(a){return o.call(arguments,1).forEach(function(b){for(var c=Object.keys(b),d=0,e=c.length;e>d;d++){var f=c[d];a[f]=b[f]}}),a}function h(a){this.ad=g({},a||{}),this.line=1,this.index=0,this.ah=0}function i(a){this.ad=g({},a||{})}function j(a){this.ad=g({},a||{},da)}function k(a){this.ad=g({},a||{})}var l={},m=Array.prototype,n=m.push,o=m.slice,p=m.splice,q=String.fromCharCode,r="Comment",s="WhiteSpace",t="LineTerminator",u="Template",v="String",w="Punctuator",x="RegularExpression",y="Numeric",z="Identifier",A="Null",B="Boolean",C="Keyword",D="\\r\\n\\u2028\\u2029",E="(?:\\r\\n|["+D+"])",F="(?:(?!["+D+"])\\s)+",G="(?=\\s*(?:(?!\\s*[/\\\\<>*%`^\"'\\w$-])[^/\\\\<>*%`^'\"({[\\w$-]|[!=]==?|[|][|]|&&|/[*/]|[,.;:!?)}\\]"+D+"]|$))",H="(?:>>>=?|[.]{3}|<<=|===|!==|>>=|[+][+](?=[+])|--(?=-)|[=!<>*%+/&|^-]=|&&|[|][|]|[+][+]|--|<<|>>|=>|[-+*/%<>=&|^~!?:;,.()[\\]{}])",I="(?:/(?![*/])(?:\\\\[\\s\\S]|\\[(?:\\\\[\\s\\S]|[^\\]"+D+"\\\\])*\\]|[^/"+D+"\\\\])+/(?:[gimuy]+\\b|))",J="`(?:\\\\[\\s\\S]|[$][{](?:\\\\[\\s\\S]|[^{}\\\\]|[{](?:[^{}]*(?:[{][^{}]*[}])?)*[}])*[}]|[^`\\\\])*`",K="(?:\\\\u(?:[0-9a-fA-F]{4}|[{][0-9a-fA-F]+[}])|[^\\s\\\\+/%*=&|^~<>!?:;,.()[\\]{}'\"`@#-])+",L="typeof|in|void|case|instanceof|yield|throw|delete|else|return|do",M="if|while|for|with",N=new RegExp("^(?:"+M+"|"+L+"|var|function|this|new|break|catch|finally|try|default|continue|switch|const|export|import|class|extends|debugger|super|let|static|enum|await|implements|package|protected|interface|private|public)$"),O=new RegExp(E),P=new RegExp("^"+K+"$"),Q=new RegExp("^"+K),R=new RegExp(K+"$"),S=/^[+-]/,T=/[+-]$/,U=/[^{}()[\]<>=!+*%\/&|^~?:;,.-]/,V=new RegExp("^"+F),W=new RegExp("(?:(?:^(?:"+L+")$)|(?:(?![.\\]])"+H+"$))"),X=new RegExp("^(?:"+M+")$"),Y=a(s),Z=a(u),$=a(x),_=a();D=E=F=G=H=I=J=K=L=M=null,h.prototype={ae:function(a,b){for(var c,d,e,f,g,h,i,j,k,l,m,n=0;n<a.length;n++)if(d=a[n],e=d.length,0!==e){if(h=this.line,i=this.index-this.ah,m=null,l=this.bc(d),this.ad.loc&&(l===v||l===r&&"*"===d.charAt(1)?(g=d.split(O),g.length>1&&(this.line+=g.length-1,this.ah=this.index+e-g.pop().length)):l===t&&(this.line++,this.ah=this.index+e)),l===x){if(this.ap(a,n,b,d)){n--;continue}f=d.lastIndexOf("/"),m={pattern:d.substr(1,f-1),flags:d.substring(f+1)}}else if(l===u){this.ak(d,b,i);continue}this.index+=e,l&&(this.ad.parse&&l===t?k=!0:l===r&&!this.ad.comment||l===s&&!this.ad.whiteSpace||l===t&&!this.ad.lineTerminator||(c={type:l,value:d},k&&(c.hasLineTerminator=!0),k=!1,m&&(c.regex=m),this.ad.range&&(c.range=[this.index-e,this.index]),this.ad.loc&&(j=this.index-this.ah,this.ai(c,h,i,this.line,j)),b[b.length]=c))}},bc:function(a){var b,f=a.length,g=a.charAt(0);switch(g){case'"':case"'":return v;case"/":return 1===f?w:(g=a.charAt(1),"/"===g||"*"===g?r:2===f&&"="===g?w:x);case".":return 1===f?w:(g=a.charAt(1),"."===g?w:y);case"<":return f>1&&"!"===a.charAt(1)?r:w;case"-":return 3>f?w:r;case"`":return u;case"}":return 1===f?w:u;default:if("true"===a||"false"===a)return B;if("null"===a)return A;if(V.test(g))return s;if(d(g))return w;if(b=g.charCodeAt(0),c(b))return t;if(e(b))return y;if(N.test(a))return C;if(P.test(a))return z}},ai:function(a,b,c,d,e){a.loc={start:{line:b,column:c},end:{line:d,column:e}}},ak:function(a,b,c){var d=this.al(a,c),e=this.am(d);n.apply(b,e)},am:function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];if("tmp-source"===e.type){var f=g({},e.ag,{type:u}),h=this.ac(e.value,f);n.apply(b,h)}else b[b.length]=e}return b},al:function(a,b){for(var d,e,f,g,h,i,j,k,l=a.match(Z),m=this.line,n=m,o=this.index,p=[this.ah],q=[],r=0,s="",t=u,v=0,w=0,x=0,y=l.length;y>x;g=l[x++]){var z=l[x],A=z.length;if(c(z.charCodeAt(0))&&(m++,p[p.length]=o+w+A),h){switch(z){case"{":v++;break;case"}":v--}0===v&&y>x+1&&"}"===l[x+1]&&(j=!0,t="tmp-source",h=!1)}else"\\"===z?"\\"===g?r++:r=1:"$"===z?i="\\"!==g||r%2===0:"{"===z&&i&&"$"===g&&(j=!0,t=u,h=!0);s+=z,x===y-1&&(j=!0,t=u),j&&(k={type:t,value:s},d=o+w+A,e=this.ao(p,d),f=d-e,t===u?(this.ad.range&&(k.range=[d-s.length,d]),this.ad.loc&&this.ai(k,n,b,m,f),b=f+A):(d=o+w+A-s.length,e=this.ao(p,d),k.ag={line:n,index:d,ah:e},b=f),q[q.length]=k,s="",n=m,j=!1),w+=A}return this.line=n,this.index=d,this.ah=e,q},ao:function(a,b){for(var c=a.length-1;c>=0;--c){var d=a[c];if(b>=d)return d}},ap:function(a,b,c,d){for(var e=c.length;--e>=0;){var f=c[e],g=f.type;if(g!==r&&g!==s&&g!==t){var h=f.value;if(g===w){if(")"===h){if(this.aq(c,e+1))break}else if(W.test(h))break}else if(g===C&&W.test(h)||g===u&&"${"===h.slice(-2))break;var i=d.match($);return p.apply(a,[b,1].concat(i)),!0}}return!1},aq:function(a,b){for(var c,d,e,f=0;--b>=0;)if(c=a[b],c.type===w)if(d=c.value,"("===d){if(0===--f)return e=a[b-1],e&&e.type===C&&X.test(e.value)?!0:!1}else")"===d&&f++;return!1},ac:function(a,b){var c=new h(this.ad);return g(c,b),c.tokenize(a)},tokenize:function(a){if(null==a)return[];a=""+a;var b;b=this.ad.whiteSpace||this.ad.range||this.ad.loc?_:Y;var c=[],d=a.match(b);return d&&this.ae(d,c),c}};var aa=l.tokenize=function(a,b){return new h(b).tokenize(a)};i.prototype={untokenize:function(a){for(var b,c=[],d=0,e=a.length;e>d;b=a[d++]){var f=a[d],g=f.type,h=f.value;if(b&&!this.ad.unsafe){var i,j=b.value;i=g===w?S.test(h)&&T.test(j):Q.test(h)&&R.test(j),c[c.length]=(i?" ":"")+h}else c[c.length]=h}return c.join("")}};var ba=l.untokenize=function(a,b){return new i(b).untokenize(a)},ca={},da={maxLineLen:32e3};j.prototype={init:function(){this.index=0,this.ar=0,this.at()},as:function(){return this.index++,this.at()},at:function(){return this.length=this.af.length,this.an=this.af[this.index-1]||{},this.aj=this.af[this.index]||ca,this.value=this.aj.value,this.type=this.aj.type,this.au=this.af[this.index+1]||ca,this.aj},av:function(a){null==a&&(a=this.index),this.af.splice(a,1),this.at()},bd:function(a){this.af.splice(this.index+1,0,a),this.as()},aw:function(a){for(a=a||t;this.type===a;)this.av()},ax:function(){for(this.init(),this.aw();this.index<this.length;){if(this.type===t){if(this.an.type===w||this.an.type===t||this.au.type===w){this.aw();continue}if(this.au.type===t){this.as(),this.aw();continue}}this.as()}},ay:function(){for(this.init();this.index<this.length;)this.type===t?this.ar=0:(this.ar+=this.value.length,this.ar>=this.ad.maxLineLen&&(this.type!==w||T.test(this.value)||(this.bd({type:t,value:"\n"}),this.ar=0))),this.as()},az:function(){this.ax(),this.ay()},minify:function(a){return this.af=aa(a,{lineTerminator:!0}),this.init(),this.az(),ba(this.af)}};var ea=(l.minify=function(a,b){return new j(b).minify(a);
},"AssignmentExpression"),fa="AssignmentPattern",ga="ArrayExpression",ha="ArrayPattern",ia="ArrowFunctionExpression",ja="ArrowParameters",ka="BlockStatement",la="BinaryExpression",ma="BreakStatement",na="CallExpression",oa="CatchClause",pa="ClassBody",qa="ClassDeclaration",ra="ClassExpression",sa="ConditionalExpression",ta="ContinueStatement",ua="DoWhileStatement",va="DebuggerStatement",wa="EmptyStatement",xa="ExportAllDeclaration",ya="ExportDefaultDeclaration",za="ExportNamedDeclaration",Aa="ExportSpecifier",Ba="ExpressionStatement",Ca="ForStatement",Da="ForOfStatement",Ea="ForInStatement",Fa="FunctionDeclaration",Ga="FunctionExpression",Ha="IfStatement",Ia="ImportDeclaration",Ja="ImportDefaultSpecifier",Ka="ImportNamespaceSpecifier",La="ImportSpecifier",Ma="Literal",Na="LabeledStatement",Oa="LogicalExpression",Pa="MemberExpression",Qa="MethodDefinition",Ra="NewExpression",Sa="ObjectExpression",Ta="ObjectPattern",Ua="Program",Va="Property",Wa="RestElement",Xa="ReturnStatement",Ya="SequenceExpression",Za="SpreadElement",$a="Super",_a="SwitchCase",ab="SwitchStatement",bb="TaggedTemplateExpression",cb="TemplateElement",db="TemplateLiteral",eb="ThisExpression",fb="ThrowStatement",gb="TryStatement",hb="UnaryExpression",ib="UpdateExpression",jb="VariableDeclaration",kb="VariableDeclarator",lb="WhileStatement",mb="WithStatement",nb="YieldExpression",ob=/^(?:[-+*%\/&|]?=|>>>?=|<<=)$/,pb=/^(?:[-+!~]|\+\+|--|typeof|void|delete)$/,qb=/^0[0-7]+$/;k.prototype={as:function(){this.aj===ca&&this.bf(),this.aj=this.af[++this.index]||ca,this.value=this.aj.value,this.type=this.aj.type},au:function(){return this.af[this.index+1]||ca},be:function(a){this.value!==a&&this.bf()},bg:function(a){this.type!==a&&this.bf()},bh:function(a){this.value!==a&&this.bf(),this.as()},bi:function(a){this.type!==a&&this.bf(),this.as()},bj:function(){return";"===this.value?(this.as(),!0):"}"===this.value||this.aj.hasLineTerminator||this.aj===ca?!0:void this.bf()},bf:function(){var a="Unexpected";if(this.aj===ca)a+=" end of input";else{var b=this.value||"";b.length>16&&(b=b.substr(0,16)+"..."),a+=" token '"+b+"'"}this.bk(a)},bk:function(a){var b=this.aj.loc;throw b&&(a+=" at line "+b.start.line+" column "+b.start.column),new Error(a)},dy:function(a){var b={};return this.dz(b),b.type=a,b},ec:function(a){if(this.ed&&this.ed.expr===a){var b=this.ed.dy,c=this.ed.ee;return this.ed=null,this.dz(a,b),this.ef(a,c)}return this.ef(a)},dz:function(a,b){if(b=b||this.aj,b===ca&&(0===this.length?b=this.eg():this.bf()),this.ad.range&&(a.range=a.range||[],a.range[0]=b.range[0]),this.ad.loc){var c=b.loc;a.loc=a.loc||{},a.loc.start={line:c.start.line,column:c.start.column}}return a},ef:function(a,b){return b=b||this.af[this.index-1],b||(0===this.length?b=this.eg():this.bf()),this.ad.range&&(a.range[1]=b.range[1]),this.ad.loc&&(a.loc.end={line:b.loc.end.line,column:b.loc.end.column}),a},eg:function(){return{range:[0,0],loc:{start:{line:0,column:0},end:{line:0,column:0}}}},bl:function(a){var b,c=0,d=a.charAt(c++);if("0"===d&&(d=a.charAt(c++),b=a.substring(c),"."!==d)){switch(d.toLowerCase()){case"x":return parseInt(b,16);case"o":return parseInt(b,8);case"b":return parseInt(b,2)}if(qb.test(a))return parseInt(d+b,8)}return parseFloat(a)},bm:function(a){for(var d,e,g,h,i,j,k="",l=1,m=a.length-1;m>l;){if(d=a.charAt(l++),"\\"===d){if(m>l&&(e=a.charCodeAt(l),c(e))){l++,13===e&&m>l&&10===a.charCodeAt(l)&&l++;continue}switch(d=a.charAt(l++)){case"b":d="\b";break;case"t":d="\t";break;case"r":d="\r";break;case"n":d="\n";break;case"v":d="\x0B";break;case"f":d="\f";break;case"u":case"x":"u"===d&&m>l&&"{"===a.charAt(l)?(l++,i=a.indexOf("}",l),~i||this.bf(),g=a.substring(l,i),l=i+1):(j="u"===d?4:2,g=a.substr(l,j),l+=j),d=b(parseInt(g,16));break;default:if(f(d)){h=d;do{if(d=a.charAt(l),!f(d))break;h+=d}while(l++<m&&h.length<3);h.length>0&&"0"===h.charAt(0)&&(h=h.substring(1)),d=q(parseInt(h,8))}}}k+=d}return k},bn:function(){var a,b,c=this.dy(Ma),d=this.value;switch(this.type){case y:a=this.bl(d);break;case v:a=this.bm(d);break;case x:b=this.aj.regex;try{a=new RegExp(b.pattern,b.flags)}catch(e){a=null}break;case B:a="true"===d;break;case A:a=null;break;default:this.bf()}return this.as(),c.value=a,c.raw=d,b&&(c.regex=b),this.ec(c)},bo:function(a){var b=this.dy(z),c=this.value;return a?this.as():this.bi(z),b.name=c,this.ec(b)},el:function(a,b,c,d,e){for(this.bh(a);this.value!==b;)c[c.length]=d.apply(this,e),this.value!==b&&this.bh(",");return this.bh(b),c},bp:function(){switch(this.type){case y:case v:case x:case B:case A:return this.bn();case z:return this.bo();case C:return this.bq();case w:return this.br();case u:return this.eh();default:this.bf()}},bq:function(){switch(this.value){case"function":return this.bs();case"class":return this.fm();case"this":return this.bt()}this.bf()},bt:function(){var a=this.dy(eb);return this.bh("this"),this.ec(a)},br:function(){switch(this.value){case"{":return this.bu();case"[":return this.bv();case"(":return this.ei();default:this.bf()}},ei:function(){var a=this.dy();if(this.bh("("),")"===this.value)return this.as(),this.be("=>"),{type:ja,params:[],dy:a};var b=this.dy(),c=this.bw(!0);if(this.ed={expr:c,dy:b,ee:this.af[this.index-1]},this.bh(")"),"=>"===this.value){var d=[];c.type===Ya?d=c.expressions:c.type===z?d=[c]:this.bf(),c={type:ja,params:d,dy:a}}return c},bu:function(){var a=this.dy(Sa);return a.properties=this.el("{","}",[],this.bx),this.ec(a)},bx:function(){var a;return a="get"===this.value||"set"===this.value?this.by():this.bz()},bz:function(){var a,b=this.dy(Va),c=!1;"*"===this.value?(a=!0,this.as()):"["===this.value&&(c=!0);var d,e=this.cc();return":"===this.value?(this.as(),d=this.cd(!0)):"("===this.value?d=this.ce({expression:!0,generator:a}):e.type===z?d="="===this.value?this.ex(e):e:this.bf(),b.key=e,b.computed=c,b.value=d,b.kind="init",this.ec(b)},by:function(){var a,b,c=this.dy(Va),d=this.au(),e=!1,f="init";return":"===d.value?(a=this.cc(),this.as(),b=this.cd(!0)):"("===d.value?(a=this.cc(),b=this.ce({expression:!0})):(f=this.value,this.as(),"["===this.value&&(e=!0),e||this.type===z||this.type===C||this.type===v||this.type===y?(a=this.cc(),b=this.ce({cf:"get"===f,cg:"set"===f,expression:!0})):this.bf()),c.key=a,c.computed=e,c.value=b,c.kind=f,this.ec(c)},cc:function(){var a;switch(this.type){case v:case y:return this.bn();case w:if("["===this.value)return this.as(),a=this.cd(),this.bh("]"),a;break;case C:case z:case B:case A:return this.bo(!0)}this.bf()},bv:function(){var a=this.dy(ga),b=[];
for(this.bh("[");"]"!==this.value;)","!==this.value?("..."===this.value?b[b.length]=this.em():b[b.length]=this.cd(!0),"]"!==this.value&&this.bh(",")):(this.as(),b[b.length]=null);return this.bh("]"),a.elements=b,this.ec(a)},em:function(){var a=this.en();return a.type=Za,a},bw:function(a){var b=this.dy(Ya),c=this.cd(a);if(","!==this.value)return c;var d=[c];do this.as(),d[d.length]=this.cd(a);while(","===this.value);return b.expressions=d,this.ec(b)},fs:function(a){var b,c;switch(a.type){case ea:a.type=fa,this.fs(a.left);break;case ga:for(a.type=ha,b=0,c=a.elements.length;c>b;b++)null!==a.elements[b]&&this.fs(a.elements[b]);break;case Sa:for(a.type=Ta,b=0,c=a.properties.length;c>b;b++)this.fs(a.properties[b].value)}},cd:function(a){if(this.fj&&"yield"===this.value)return this.fk();var b=this.dy(ea),c=this.ch(a);if("=>"===this.value||c.type===ja)return c.type===z&&(c.params=[g({},c)],c.dy=b),this.eo(c);if(!ob.test(this.value))return c;this.fs(c);var d=this.value;this.as();var e=this.cd(a);return b.operator=d,b.left=c,b.right=e,this.ec(b)},ch:function(a){var b=this.dy(sa),c=this.ci(a);if("?"!==this.value)return c;this.bh("?");var d=this.cd(!0);this.bh(":");var e=this.cd(a);return b.test=c,b.consequent=d,b.alternate=e,this.ec(b)},eo:function(a){var b=this.dy(ia);this.dz(b,a.dy),this.bh("=>");var c,d=a.params||[],e=!1;return"{"===this.value?c=this.ct():(c=this.cd(!0),e=!0),b.params=d,b.body=c,b.expression=e,this.ec(b)},fk:function(){var a=this.dy(nb),b=null,c=!1;return this.bh("yield"),this.aj.hasLineTerminator||("*"===this.value?(c=!0,this.as(),b=this.cd(!0)):";"!==this.value&&"}"!==this.value&&this.aj!==ca&&(b=this.cd(!0))),a.argument=b,a.delegate=c,this.ec(a)},cj:function(a){switch(this.value){case"*":case"/":case"%":return 1;case"+":case"-":return 2;case"<<":case">>":case">>>":return 3;case"<":case">":case"<=":case">=":case"instanceof":return 4;case"in":return a?4:0;case"==":case"!=":case"===":case"!==":return 5;case"&":return 6;case"^":return 7;case"|":return 8;case"&&":return 9;case"||":return 10;default:return 0}},ci:function(a,b){null==b&&(b=10);var c=this.dy(),d=this.ck(),e=this.cj(a);if(!e)return d;for(var f,g,h,i=1;10>=i;i++){for(;(e=this.cj(a))===i;)g=this.value,h=this.dy(9>i?la:Oa),this.dz(h,c),h.operator=g,h.left=d,this.as(),f=1===e?this.ck():this.ci(a,e-1),h.right=f,d=this.ec(h);if(e>b)break}return this.dz(d,c),this.ec(d)},ck:function(){var a=this.value;if(!pb.test(a))return this.cl();var b="++"===a||"--"===a,c=this.dy(b?ib:hb);this.as();var d=this.ck();return c.operator=a,c.argument=d,c.prefix=!0,this.ec(c)},cl:function(){var a=this.dy(ib),b=this.cm(!0),c=this.value;return"++"===c||"--"===c?(this.as(),a.operator=c,a.argument=b,a.prefix=!1,this.ec(a)):b},cm:function(a){var b,c=this.dy();for(b="super"===this.value?this.fn():"new"===this.value?this.cn():this.bp();;)if("."===this.value)b=this.co(b,c);else if("["===this.value)b=this.cp(b,c);else if(a&&"("===this.value)b=this.cq(b,c);else{if(this.type!==u||"`"!==this.value.charAt(0))break;b=this.ej(b,c)}return b},fn:function(){var a=this.dy($a);return this.bh("super"),this.ec(a)},cn:function(){var a=this.dy(Ra);this.as();var b=this.cm(!1);return a.callee=b,a.arguments=[],"("===this.value&&this.cr(a),this.ec(a)},cq:function(a,b){var c=this.dy(na);return this.dz(c,b),c.callee=a,c.arguments=[],this.cr(c),this.ec(c)},cp:function(a,b){var c=this.dy(Pa);return this.dz(c,b),this.as(),c.computed=!0,c.object=a,c.property=this.bw(!0),this.bh("]"),this.ec(c)},co:function(a,b){var c=this.dy(Pa);return this.dz(c,b),this.as(),c.computed=!1,c.object=a,c.property=this.bo(),this.ec(c)},cr:function(a){return this.el("(",")",a.arguments,this.cd,[!0]),a},eh:function(){for(var a=this.dy(db),b=this.ek(),c=[b],d=[];!b.tail;)d[d.length]=this.bw(),b=this.ek(),c[c.length]=b;return a.quasis=c,a.expressions=d,this.ec(a)},ek:function(){var a,b=this.dy(cb),c=!1;this.bg(u),"`"===this.value.slice(-1)&&(c=!0);var d=c?-1:-2;a=this.value.slice(1,d);var e=this.bm("`"+a+"`");return this.as(),b.tail=c,b.value={cooked:e,raw:a},this.ec(b)},ej:function(a,b){var c=this.dy(bb);this.dz(c,b);var d=this.eh();return c.tag=a,c.quasi=d,this.ec(c)},cs:function(){switch(this.value){case"{":return this.ct();case"var":case"let":case"const":return this.cu(this.value);case";":return this.cv();case"if":return this.cw();case"continue":return this.cx();case"break":return this.cy();case"return":return this.cz();case"with":return this.dc();case"throw":return this.dd();case"try":return this.de();case"debugger":return this.df();case"function":return this.dg();case"class":return this.fo();case"switch":return this.dh();case"do":return this.di();case"while":return this.dj();case"for":return this.dk();case"import":return this.ep();case"export":return this.eq();default:return this.dl()}},dm:function(a,b){for(;this.value!==b;)a[a.length]=this.cs()},ct:function(){var a=this.dy(ka);this.bh("{");var b=[];return this.dm(b,"}"),this.bh("}"),a.body=b,this.ec(a)},cu:function(a,b){var c=this.dy(jb),d=!b,e=this.dn(d);return b||this.bj(),c.declarations=e,c.kind=a,this.ec(c)},dn:function(a){var b=[];do b[b.length]=this.dp(a);while(","===this.value);return b},dp:function(a){this.as();var b=this.dy(kb),c=this.er(),d=null;return"="===this.value&&(this.as(),d=this.cd(a)),b.id=c,b.init=d,this.ec(b)},dg:function(){return this.es()},bs:function(){return this.es(!0)},es:function(a){var b=this.dy(),c=!1;return this.bh("function"),"*"===this.value&&(c=!0,this.as()),this.ce({node:b,generator:c,expression:a})},ce:function(a){a=a||{};var b=a.node||this.dy();
b.type=a.expression?Ga:Fa,b.id=null,b.params=[],b.defaults=[],b.body=null,b.generator=!!a.generator,b.expression=!1,a.cf?(this.bh("("),this.bh(")")):a.cg?this.dq(b):(this.type===z&&(b.id=this.bo()),this.dq(b));var c=this.fj;return this.fj=b.generator,b.body=this.ct(),this.fj=c,this.ec(b)},dq:function(a){for(this.bh("(");")"!==this.value&&this.et(a););a.fl?delete a.fl:a.defaults.length=0,this.bh(")")},et:function(a){var b=a.params,c=a.defaults;if("..."===this.value)return b[b.length]=this.en(),c[c.length]=null,!1;var d=this.eu();return d.type===fa?(b[b.length]=d.left,c[c.length]=d.right,a.fl=!0):(b[b.length]=d,c[c.length]=null),")"!==this.value&&this.bh(","),!0},en:function(){var a=this.dy(Wa);this.bh("...");var b=this.bo();return a.argument=b,this.ec(a)},er:function(){return this.type===z?this.bo():"{"===this.value?this.ev():"["===this.value?this.ew():void this.bf()},eu:function(){var a=this.er();return"="===this.value?this.ex(a):a},ex:function(a){this.bh("=");var b=this.dy(fa);this.dz(b,a);var c=this.cd(!0);return b.left=a,b.right=c,this.ec(b)},ew:function(){var a=this.dy(ha),b=[];for(this.bh("[");"]"!==this.value;){if(","===this.value)b[b.length]=null;else{if("..."===this.value){b[b.length]=this.en();break}b[b.length]=this.eu()}"]"!==this.value&&this.bh(",")}return this.bh("]"),a.elements=b,this.ec(a)},ev:function(){var a=this.dy(Ta);return a.properties=this.el("{","}",[],this.ey),this.ec(a)},ey:function(){var a,b,c=this.dy(Va);return this.type===z?(a=this.bo(),"="===this.value?(b=this.ex(a),this.dz(b,c)):":"!==this.value&&(b=a)):a=this.cc(),b||(this.bh(":"),b=this.eu()),c.key=a,c.value=b,c.kind="init",this.ec(c)},cw:function(){var a=this.dy(Ha);this.bh("if"),this.bh("(");var b=this.bw(!0);this.bh(")");var c=this.cs(),d=null;return"else"===this.value&&(this.as(),d=this.cs()),a.test=b,a.consequent=c,a.alternate=d,this.ec(a)},cv:function(){var a=this.dy(wa);return this.bh(";"),this.ec(a)},cx:function(){var a=this.dy(ta);this.bh("continue");var b=null;return this.type!==z||this.aj.hasLineTerminator||(b=this.bo()),this.bj(),a.label=b,this.ec(a)},cy:function(){var a=this.dy(ma);this.bh("break");var b=null;return this.type!==z||this.aj.hasLineTerminator||(b=this.bo()),this.bj(),a.label=b,this.ec(a)},cz:function(){var a=this.dy(Xa);this.bh("return");var b=null;return";"===this.value||"}"===this.value||this.aj.hasLineTerminator||this.aj===ca||(b=this.bw(!0)),this.bj(),a.argument=b,this.ec(a)},dc:function(){var a=this.dy(mb);this.bh("with"),this.bh("(");var b=this.bw(!0);return this.bh(")"),a.object=b,a.body=this.cs(),this.ec(a)},dd:function(){var a=this.dy(fb);this.bh("throw"),this.aj.hasLineTerminator&&this.bf();var b=this.bw(!0);return this.bj(),a.argument=b,this.ec(a)},de:function(){var a,b,c=this.dy(gb),d=null,e=null;this.bh("try");var f=this.ct();return"catch"===this.value&&(a=!0,d=this.dr()),"finally"===this.value&&(b=!0,this.as(),e=this.ct()),a||b||this.bf(),c.block=f,c.handler=d,c.finalizer=e,this.ec(c)},dr:function(){var a=this.dy(oa);this.bh("catch"),this.bh("(");var b=this.er();this.bh(")");var c=this.ct();return a.param=b,a.body=c,this.ec(a)},df:function(){var a=this.dy(va);return this.bh("debugger"),this.bj(),this.ec(a)},dh:function(){var a=this.dy(ab);this.bh("switch"),this.bh("(");var b=this.bw(!0),c=[];for(this.bh(")"),this.bh("{");"}"!==this.value;)c[c.length]=this.ds();return this.bh("}"),a.discriminant=b,a.cases=c,this.ec(a)},ds:function(){var a=this.dy(_a),b=null,c=[];for("case"===this.value?(this.as(),b=this.bw(!0)):this.bh("default"),this.bh(":");"}"!==this.value&&"case"!==this.value&&"default"!==this.value&&this.aj!==ca;)c[c.length]=this.cs();return a.test=b,a.consequent=c,this.ec(a)},dj:function(){var a=this.dy(lb);this.bh("while"),this.bh("(");var b=this.bw(!0);return this.bh(")"),a.test=b,a.body=this.cs(),this.ec(a)},di:function(){var a=this.dy(ua);this.bh("do");var b=this.cs();this.bh("while"),this.bh("(");var c=this.bw(!0);return this.bh(")"),this.bj(),a.body=b,a.test=c,this.ec(a)},dk:function(){var a=this.dy(Ca);this.bh("for"),this.bh("(");var b=null;if(";"!==this.value&&(b="var"===this.value||"let"===this.value||"const"===this.value?this.dt(a):this.du(a),b.type===Ea||b.type===Da))return b;this.bh(";");var c=null;";"!==this.value&&(c=this.bw(!0)),this.bh(";");var d=null;")"!==this.value&&(d=this.bw(!0)),this.bh(")");var e=this.cs();return a.init=b,a.test=c,a.update=d,a.body=e,this.ec(a)},du:function(a){var b=this.bw(!1);return"in"===this.value?this.dv(b,a):"of"===this.value?this.dw(b,a):b},dt:function(a){var b=this.value,c=this.cu(b,!0);return"in"===this.value?this.dv(c,a):"of"===this.value?this.dw(c,a):c},dv:function(a,b){b.type=Ea,this.bh("in");var c=this.bw(!0);this.bh(")");var d=this.cs();return b.left=a,b.right=c,b.body=d,b.each=!1,this.ec(b)},dw:function(a,b){b.type=Da,this.bh("of");var c=this.bw(!0);this.bh(")");var d=this.cs();return b.left=a,b.right=c,b.body=d,this.ec(b)},ep:function(){var a=this.dy(Ia);return this.bh("import"),a.specifiers=this.ez(),"from"===this.value&&this.as(),this.bg(v),a.source=this.bn(),this.bj(),this.ec(a)},ez:function(){var a=[];if(this.type===v)return a;if(this.type===z){if("from"===this.value&&this.bf(),a[a.length]=this.fc(),","!==this.value)return a;this.as()}if("*"===this.value){if(a[a.length]=this.fd(),","!==this.value)return a;this.as()}return"{"===this.value&&this.el("{","}",a,this.fe),a},fe:function(){var a,b=this.dy(La),c=this.bo();return"as"===this.value&&(this.as(),a=this.bo()),b.local=a||c,b.imported=c,this.ec(b)},fd:function(){var a=this.dy(Ka);return this.bh("*"),this.bh("as"),a.local=this.bo(),this.ec(a)},fc:function(){
var a=this.dy(Ja);return a.local=this.bo(),this.ec(a)},eq:function(){var a=this.dy();return this.bh("export"),"default"===this.value?this.ff(a):"*"===this.value?this.fg(a):this.fh(a)},ff:function(a){a.type=ya,this.bh("default");var b,c;return"function"===this.value?(b=this.dg(),c=!0):b=this.cd(!0),c||this.bj(),a.declaration=b,this.ec(a)},fg:function(a){return a.type=xa,this.bh("*"),this.bh("from"),this.bg(v),a.source=this.bn(),this.bj(),this.ec(a)},fh:function(a){a.type=za;var b=null,c=[],d=null;return this.type===C?b=this.cs():(this.el("{","}",c,this.fi),"from"===this.value&&(this.as(),this.bg(v),d=this.bn()),this.bj()),a.declaration=b,a.specifiers=c,a.source=d,this.ec(a)},fi:function(){var a,b=this.dy(Aa),c=this.bo();return"as"===this.value&&(this.as(),a=this.bo()),b.exported=a||c,b.local=c,this.ec(b)},fo:function(){return this.fp()},fm:function(){return this.fp(!0)},fp:function(a){var b=this.dy(a?ra:qa);this.bh("class");var c=null;this.type===z&&(c=this.bo());var d=null;return"extends"===this.value&&(this.as(),d=this.cm(!0)),b.id=c,b.superClass=d,b.body=this.fq(),this.ec(b)},fq:function(){var a=this.dy(pa),b=[];for(this.bh("{");"}"!==this.value;)";"!==this.value?b[b.length]=this.fr():this.as();return this.bh("}"),a.body=b,this.ec(a)},fr:function(){var a=this.dy(Qa),b=!1;"static"===this.value&&(b=!0,this.as());var c=this.bx();return this.dz(c,a),c.type=Qa,c["static"]=b,"constructor"===c.key.name?c.kind="constructor":"init"===c.kind&&(c.kind="method"),this.ec(c)},dl:function(){var a=this.dx();if(a)return a;var b=this.dy(Ba),c=this.bw(!0);return this.bj(),b.expression=c,this.ec(b)},dx:function(){if(this.type===z&&":"===this.au().value){var a=this.dy(Na),b=this.bo();this.as();var c=this.cs();return a.label=b,a.body=c,this.ec(a)}},parse:function(a){a=null==a?"":""+a,this.af=aa(a,{range:this.ad.range,loc:this.ad.loc,parse:!0}),this.length=this.af.length,this.index=-1,this.as();var b=this.dy(Ua);return b.body=[],this.dm(b.body),this.ec(b)}};l.parse=function(a,b){return new k(b).parse(a)};return l});
var window = window || exports;
if(window) {
window.PNGDrive=function(b,a){this.VERSION_MAJOR=1;this.VERSION_MINOR=0;this.files=[];this.raw=new Uint8Array(0);if(typeof b!=="undefined"){this.decode(b,a)}};window.PNGDrive.prototype={addFile:function(a){this.files.push({name:a.name,type:a.type,fileRef:a})},addTextFile:function(c,a,b){this.files.push({name:a,type:b,content:this.utf8Encode(c)})},addBinaryFile:function(c,a,b){this.files.push({name:a,type:b,content:c})},removeAll:function(){this.files=[]},removeFileAt:function(a){if(a>=0&&a<this.files.length){this.files.splice(a,1)}},removeFileByName:function(a){for(var b=0;b<this.files.length;b++){if(this.files[b].name==a){this.files.splice(b,1);break}}},getFileCount:function(){return this.files.length},getFileAt:function(a){return(a>=0&&a<this.files.length)?this.files[a]:null},getFileByName:function(a){for(var b=0;b<this.files.length;b++){if(this.files[b].name==a){return this.files[b]}}return null},decode:function(h,q){if(typeof q=="undefined"){q=8}var d=document.createElement("canvas");var r=d.getContext("2d");d.width=h.width;d.height=h.height;r.drawImage(h,0,0);var m=r.getImageData(0,0,h.width,h.height);var b=m.data;var c=b.length;var e=this.raw=new Uint8Array(h.width*h.height*3);var l=0;if(q==8){var k=0;while(l<c){if(b[l+3]==255){e[k++]=b[l++];e[k++]=b[l++];e[k++]=b[l++];l++}else{l+=4}}}else{var n=new PNGDriveBitStream(e);while(l<c){if(b[l+3]==255){n.writeBits(q,b[l++]);n.writeBits(q,b[l++]);n.writeBits(q,b[l++]);l++}else{l+=4}}}if(e[0]==218&&e[1]==218){var p=e[4]|e[5]<<8|e[6]<<16|e[7]<<24;var a=e.subarray(8,8+p);var g=JSON.parse(this.utf8Decode(a));var o=8+p;this.files=[];for(l=0;l<g.files.length;l++){var f=g.files[l];var s=new Uint8Array(f.size);s.set(e.subarray(o,o+f.size));o+=f.size;this.files.push({name:f.name,type:f.type,content:s})}}return this},encode:function(b){var a=this;(function(g){var f=0;var h=a.getFileCount();for(var e=0;e<h;e++){var d=a.files[e];if(d.fileRef){f++;var c=new FileReader();c.onload=(function(i){return function(j){i.content=new Uint8Array(j.target.result);delete i.fileRef;if(--f==0&&e==h){f=-1;g.call(a)}}})(d);c.readAsArrayBuffer(d.fileRef)}}if(f==0){g.call(a)}})(function(){var e=this.getFileCount();if(e>0){var h,i,f;var g={files:[]};var m=0;for(h=0;h<e;h++){f=this.files[h];m+=f.content.byteLength;g.files.push({name:f.name,size:f.content.byteLength,type:f.type})}var c=this.utf8Encode(JSON.stringify(g));var l=c.byteLength;var k=8+l+m;var d=this.raw=new Uint8Array(k);d[0]=d[1]=218;d[2]=this.VERSION_MAJOR;d[3]=this.VERSION_MINOR;d[4]=l&255;d[5]=(l>>8)&255;d[6]=(l>>16)&255;d[7]=(l>>24)&255;d.set(c,8);for(h=0,i=8+c.byteLength;h<e;h++){f=this.files[h];d.set(f.content,i);i+=f.content.byteLength}}else{this.raw=new Uint8Array(0)}if(b){b.call(this)}})},createImage:function(k,l){var b=document.createElement("canvas");var m=b.getContext("2d");if(typeof k=="undefined"){l=8;var h=Math.ceil(Math.sqrt(this.raw.byteLength/3));b.width=h;b.height=h;m.fillRect(0,0,h,h)}else{if(typeof l=="undefined"){l=8}b.width=k.width;b.height=k.height;m.drawImage(k,0,0)}var e=m.getImageData(0,0,b.width,b.height);var a=e.data;var n=a.length;var d=0;if(l==8){var c=0;while(d<n){if(a[d+3]==255){a[d++]=this.raw[c++];a[d++]=this.raw[c++];a[d++]=this.raw[c++];d++}else{d+=4}}}else{var f=new PNGDriveBitStream(this.raw);var g=255^(255>>>(8-l));while(d<n){if(a[d+3]==255){a[d]=(a[d++]&g)|f.readBits(l);a[d]=(a[d++]&g)|f.readBits(l);a[d]=(a[d++]&g)|f.readBits(l);d++}else{d+=4}}}m.putImageData(e,0,0);return b},computeImageCapacity:function(g,h){if(typeof h=="undefined"){h=8}var b=document.createElement("canvas");var j=b.getContext("2d");b.width=g.width;b.height=g.height;j.drawImage(g,0,0);var d=j.getImageData(0,0,b.width,b.height);var a=d.data;var k=a.length;var c=0;var e=0;var f=h*3;while(c<k){if(a[c+3]==255){e+=f}c+=4}return e},utf8Encode:function(b){var d=[];var a=b.length;for(var f=0;f<a;f++){var e=b.charCodeAt(f);if(e<128){d.push(e)}else{if((e>127)&&(e<2048)){d.push((e>>6)|192);d.push((e&63)|128)}else{d.push((e>>12)|224);d.push(((e>>6)&63)|128);d.push((e&63)|128)}}}return new Uint8Array(d)},utf8Decode:function(b){var a=b.byteLength;var d="";var e=0;while(e<a){var f=b[e];if(f<128){d+=String.fromCharCode(f);e++}else{if((f>191)&&(f<224)&&(e+1<a)){d+=String.fromCharCode(((f&31)<<6)|(b[e+1]&63));e+=2}else{if(e+2<a){d+=String.fromCharCode(((f&15)<<12)|((b[e+1]&63)<<6)|(b[e+2]&63));e+=3}}}}return d}};window.PNGDriveBitStream=function(a){this.a=a;this.position=0;this.bitsPending=0};window.PNGDriveBitStream.prototype={writeBits:function(b,a){if(b==0){return}a&=(4294967295>>>(32-b));var c;if(this.bitsPending>0){if(this.bitsPending>b){this.a[this.position-1]|=a<<(this.bitsPending-b);c=b;this.bitsPending-=b}else{if(this.bitsPending==b){this.a[this.position-1]|=a;c=b;this.bitsPending=0}else{this.a[this.position-1]|=a>>(b-this.bitsPending);c=this.bitsPending;this.bitsPending=0}}}else{c=Math.min(8,b);this.bitsPending=8-c;this.a[this.position++]=(a>>(b-c))<<this.bitsPending}b-=c;if(b>0){this.writeBits(b,a)}},readBits:function(e,c){if(typeof c=="undefined"){c=0}if(e==0){return c}var d;var f;if(this.bitsPending>0){var a=this.a[this.position-1]&(255>>(8-this.bitsPending));f=Math.min(this.bitsPending,e);this.bitsPending-=f;d=a>>this.bitsPending}else{f=Math.min(8,e);this.bitsPending=8-f;d=this.a[this.position++]>>this.bitsPending}e-=f;c=(c<<f)|d;return(e>0)?this.readBits(e,c):c},seekTo:function(a){this.position=(a/8)|0;this.bitsPending=a%8;if(this.bitsPending>0){this.bitsPending=8-this.bitsPending;this.position++}}};
}exports.mainEntry();
/* global exports:true, module:true, require:true, define:true, global:true */
